1. patch from Toby that allows repeated labels to be placed on a line
geometry (such as roads) 2. restored text labels for point geometry. 3. process 'spacing' attribute in load_map.cpp
This commit is contained in:
parent
51906ed2f8
commit
e924b597f4
10 changed files with 228 additions and 188 deletions
|
@ -49,6 +49,9 @@ void export_text_symbolizer()
|
|||
.add_property("text_ratio",
|
||||
&text_symbolizer::get_text_ratio,
|
||||
&text_symbolizer::set_text_ratio)
|
||||
.add_property("label_spacing",
|
||||
&text_symbolizer::get_label_spacing,
|
||||
&text_symbolizer::set_label_spacing)
|
||||
.add_property("halo_radius",
|
||||
&text_symbolizer::get_halo_radius,
|
||||
&text_symbolizer::set_halo_radius)
|
||||
|
|
|
@ -280,11 +280,13 @@ popplaces_rule = Rule()
|
|||
# The first parameter is the name of the attribute to use as the source of the
|
||||
# text to label with. Then there is font size in points (I think?), and colour.
|
||||
|
||||
popplaces_text_symbolizer = TextSymbolizer('GEONAME', 10, Color('black'))
|
||||
popplaces_text_symbolizer = TextSymbolizer('GEONAME',
|
||||
'Bitstream Vera Sans Roman',
|
||||
10, Color('black'))
|
||||
|
||||
# We set a "halo" around the text, which looks like an outline if thin enough,
|
||||
# or an outright background if large enough.
|
||||
|
||||
popplaces_text_symbolizer.set_label_placement=label_placement.POINT_PLACEMENT
|
||||
popplaces_text_symbolizer.halo_fill = Color('white')
|
||||
popplaces_text_symbolizer.halo_radius = 1
|
||||
popplaces_rule.symbols.append(popplaces_text_symbolizer)
|
||||
|
|
|
@ -36,6 +36,15 @@
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
struct placement_element
|
||||
{
|
||||
double starting_x;
|
||||
double starting_y;
|
||||
|
||||
text_path path;
|
||||
};
|
||||
|
||||
struct placement
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
@ -48,7 +57,8 @@ namespace mapnik
|
|||
|
||||
~placement();
|
||||
|
||||
string_info *info;
|
||||
unsigned path_size() const;
|
||||
string_info *info;
|
||||
|
||||
CoordTransform *ctrans;
|
||||
const proj_transform *proj_trans;
|
||||
|
@ -63,11 +73,10 @@ namespace mapnik
|
|||
std::queue< Envelope<double> > envelopes;
|
||||
|
||||
//output
|
||||
double starting_x;
|
||||
double starting_y;
|
||||
|
||||
text_path path;
|
||||
std::vector<placement_element> placements;
|
||||
|
||||
// caching output
|
||||
placement_element current_placement;
|
||||
|
||||
//helpers
|
||||
std::pair<double, double> get_position_at_distance(double target_distance);
|
||||
|
@ -78,14 +87,18 @@ namespace mapnik
|
|||
|
||||
int wrap_width;
|
||||
int text_ratio;
|
||||
|
||||
int label_spacing; // distance between repeated labels on a single geometry
|
||||
};
|
||||
|
||||
|
||||
|
||||
class placement_finder : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
placement_finder(Envelope<double> e);
|
||||
|
||||
bool find_placement(placement *placement);
|
||||
bool find_placements(placement *p);
|
||||
|
||||
protected:
|
||||
bool find_placement_follow(placement *p);
|
||||
|
|
|
@ -93,9 +93,9 @@ namespace mapnik
|
|||
}
|
||||
};
|
||||
|
||||
struct text_path : private boost::noncopyable
|
||||
struct text_path
|
||||
{
|
||||
struct character_node : boost::noncopyable
|
||||
struct character_node
|
||||
{
|
||||
int c;
|
||||
double x, y, angle;
|
||||
|
@ -112,7 +112,7 @@ namespace mapnik
|
|||
}
|
||||
};
|
||||
|
||||
typedef boost::ptr_vector<character_node> character_nodes_t;
|
||||
typedef std::vector<character_node> character_nodes_t;
|
||||
|
||||
character_nodes_t nodes_;
|
||||
int itr_;
|
||||
|
@ -120,11 +120,17 @@ namespace mapnik
|
|||
std::pair<unsigned,unsigned> string_dimensions;
|
||||
|
||||
text_path() : itr_(0) {}
|
||||
text_path(const text_path & other) : itr_(0)
|
||||
{
|
||||
nodes_ = other.nodes_;
|
||||
string_dimensions = other.string_dimensions;
|
||||
}
|
||||
|
||||
~text_path() {}
|
||||
|
||||
void add_node(int c, double x, double y, double angle)
|
||||
{
|
||||
nodes_.push_back(new character_node(c, x, y, angle));
|
||||
nodes_.push_back(character_node(c, x, y, angle));
|
||||
}
|
||||
|
||||
void vertex(int *c, double *x, double *y, double *angle)
|
||||
|
|
|
@ -45,8 +45,10 @@ namespace mapnik
|
|||
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
|
||||
unsigned get_wrap_width() const; // width to wrap text at, or trigger ratio
|
||||
void set_wrap_width(unsigned ratio);
|
||||
unsigned get_label_spacing() const; // spacing between repeated labels on lines
|
||||
void set_label_spacing(unsigned spacing);
|
||||
unsigned get_text_size() const;
|
||||
std::string const& get_face_name() const;
|
||||
Color const& get_fill() const;
|
||||
|
@ -66,6 +68,7 @@ namespace mapnik
|
|||
unsigned size_;
|
||||
unsigned text_ratio_;
|
||||
unsigned wrap_width_;
|
||||
unsigned label_spacing_;
|
||||
Color fill_;
|
||||
Color halo_fill_;
|
||||
unsigned halo_radius_;
|
||||
|
|
|
@ -148,7 +148,7 @@ postgis_datasource::postgis_datasource(const parameters& params)
|
|||
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double,false,length));
|
||||
case 1042: // bpchar
|
||||
case 1043: // varchar
|
||||
case 25: // text
|
||||
case 25: // text
|
||||
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
|
||||
break;
|
||||
default: // shouldn't get here
|
||||
|
|
|
@ -346,24 +346,26 @@ namespace mapnik
|
|||
|
||||
placement text_placement(&info, &t_, &prj_trans, geom, std::pair<double, double>(w, h) );
|
||||
|
||||
bool found = finder_.find_placement(&text_placement);
|
||||
bool found = finder_.find_placements(&text_placement);
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
double x = text_placement.starting_x;
|
||||
double y = text_placement.starting_y;
|
||||
|
||||
int px=int(floor(x - 0.5 * w));
|
||||
int py=int(floor(y - 0.5 * h));
|
||||
|
||||
pixmap_.set_rectangle_alpha(px,py,*data);
|
||||
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.path);
|
||||
|
||||
//If has_placement
|
||||
|
||||
ren.render(x,y);
|
||||
|
||||
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;
|
||||
|
||||
int px=int(floor(x - 0.5 * w));
|
||||
int py=int(floor(y - 0.5 * h));
|
||||
|
||||
pixmap_.set_rectangle_alpha(px,py,*data);
|
||||
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path);
|
||||
|
||||
ren.render(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,33 +498,37 @@ namespace mapnik
|
|||
ren.set_fill(fill);
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius());
|
||||
|
||||
|
||||
string_info info;
|
||||
|
||||
|
||||
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);
|
||||
text_placement.label_spacing = sym.get_label_spacing();
|
||||
|
||||
bool found = finder_.find_placements(&text_placement);
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
double x = text_placement.starting_x;
|
||||
double y = text_placement.starting_y;
|
||||
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.path);
|
||||
|
||||
Envelope<double> text_box(x + dim.minx() ,y - dim.maxy(), x + dim.maxx(),y - dim.miny());
|
||||
|
||||
if (sym.get_halo_radius() > 0)
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
|
||||
{
|
||||
text_box.width(text_box.width() + sym.get_halo_radius()*2);
|
||||
text_box.height(text_box.height() + sym.get_halo_radius()*2);
|
||||
double x = text_placement.placements[ii].starting_x;
|
||||
double y = text_placement.placements[ii].starting_y;
|
||||
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path);
|
||||
|
||||
Envelope<double> text_box(x + dim.minx() ,y - dim.maxy(), x + dim.maxx(),y - dim.miny());
|
||||
|
||||
if (sym.get_halo_radius() > 0)
|
||||
{
|
||||
text_box.width(text_box.width() + sym.get_halo_radius()*2);
|
||||
text_box.height(text_box.height() + sym.get_halo_radius()*2);
|
||||
}
|
||||
ren.render(x,y);
|
||||
}
|
||||
ren.render(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,16 @@ namespace mapnik
|
|||
|
||||
if ( sym.first == "PointSymbolizer")
|
||||
{
|
||||
std::cout << sym.first << "\n";
|
||||
std::string file =
|
||||
sym.second.get<std::string>("<xmlattr>.file");
|
||||
std::string type =
|
||||
sym.second.get<std::string>("<xmlattr>.type");
|
||||
unsigned width =
|
||||
sym.second.get<unsigned>("<xmlattr>.width");
|
||||
unsigned height =
|
||||
sym.second.get<unsigned>("<xmlattr>.height");
|
||||
|
||||
rule.append(point_symbolizer(file,type,width,height));
|
||||
}
|
||||
else if ( sym.first == "LinePatternSymbolizer")
|
||||
{
|
||||
|
@ -163,6 +172,7 @@ 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");
|
||||
|
@ -195,6 +205,13 @@ namespace mapnik
|
|||
text_symbol.set_wrap_width(*wrap_width);
|
||||
}
|
||||
|
||||
// spacing between repeated labels on lines
|
||||
boost::optional<unsigned> spacing =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.spacing");
|
||||
if (spacing)
|
||||
{
|
||||
text_symbol.set_label_spacing(*spacing);
|
||||
}
|
||||
rule.append(text_symbol);
|
||||
}
|
||||
else if ( sym.first == "ShieldSymbolizer")
|
||||
|
|
|
@ -41,26 +41,31 @@
|
|||
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), wrap_width(0), text_ratio(0)
|
||||
: 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), label_spacing(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)
|
||||
: 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), label_spacing(0)
|
||||
{
|
||||
}
|
||||
|
||||
placement::~placement()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
unsigned placement::path_size() const
|
||||
{
|
||||
return geom->num_points();
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -132,11 +137,12 @@ namespace mapnik
|
|||
|
||||
|
||||
placement_finder::placement_finder(Envelope<double> e)
|
||||
: detector_(e)
|
||||
: detector_(e)
|
||||
{
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement(placement *p)
|
||||
|
||||
bool placement_finder::find_placements(placement *p)
|
||||
{
|
||||
if (p->label_placement == point_placement)
|
||||
{
|
||||
|
@ -156,37 +162,76 @@ namespace mapnik
|
|||
double string_width = string_dimensions.first;
|
||||
// double string_height = string_dimensions.second;
|
||||
|
||||
|
||||
std::clog << "trying to place string: ";
|
||||
for (unsigned int ii = 0; ii < p->info->num_characters(); ++ii)
|
||||
std::clog << static_cast<char> (p->info->at(ii).character);
|
||||
std::clog << std::endl;
|
||||
|
||||
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)
|
||||
if (string_width > distance)
|
||||
{
|
||||
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;
|
||||
}
|
||||
std::clog << "String longer than segment, bailing" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
int num_labels = 0;
|
||||
if (p->label_spacing)
|
||||
num_labels = static_cast<int> (floor(distance / (p->label_spacing + string_width)));
|
||||
if (num_labels == 0)
|
||||
num_labels = 1;
|
||||
|
||||
double ideal_spacing = distance/num_labels;
|
||||
std::vector<double> ideal_label_distances;
|
||||
for (double label_pos = ideal_spacing/2; label_pos < distance; label_pos += ideal_spacing)
|
||||
ideal_label_distances.push_back(label_pos);
|
||||
|
||||
double delta = distance/100.0;
|
||||
bool FoundPlacement = false;
|
||||
for (std::vector<double>::const_iterator itr = ideal_label_distances.begin(); itr < ideal_label_distances.end(); ++itr)
|
||||
{
|
||||
std::clog << "Trying to find txt placement at distance: " << *itr << std::endl;
|
||||
for (double i = 0; i < ideal_spacing; i += delta)
|
||||
{
|
||||
p->clear_envelopes();
|
||||
|
||||
// check position +- delta for valid placement
|
||||
if ( build_path_follow(p, *itr - string_width/2 + i)) {
|
||||
update_detector(p);
|
||||
FoundPlacement = true;
|
||||
break;
|
||||
}
|
||||
|
||||
p->clear_envelopes();
|
||||
if (build_path_follow(p, *itr - string_width/2 - i) ) {
|
||||
update_detector(p);
|
||||
FoundPlacement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if (FoundPlacement)
|
||||
std::clog << "Found Placement" << string_width << " " << distance << std::endl;
|
||||
|
||||
return FoundPlacement;
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement_horizontal(placement *p)
|
||||
{
|
||||
double distance = p->get_total_distance();
|
||||
if (p->path_size() == 1) // point geometry
|
||||
{
|
||||
if ( build_path_horizontal(p, 0) )
|
||||
{
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double distance = p->get_total_distance();
|
||||
//~ double delta = string_width/distance;
|
||||
double delta = distance/100.0;
|
||||
|
||||
|
@ -206,10 +251,6 @@ namespace mapnik
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -226,14 +267,14 @@ namespace mapnik
|
|||
}
|
||||
|
||||
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();
|
||||
p->current_placement.path.clear();
|
||||
|
||||
double x, y;
|
||||
x = y = 0.0;
|
||||
|
@ -265,9 +306,9 @@ namespace mapnik
|
|||
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;
|
||||
|
||||
p->current_placement.starting_x = new_x - dx*(distance - target_distance)/segment_length;
|
||||
p->current_placement.starting_y = new_y - dy*(distance - target_distance)/segment_length;
|
||||
|
||||
angle = atan2(-dy, dx);
|
||||
|
||||
if (angle > M_PI/2 || angle <= -M_PI/2) {
|
||||
|
@ -282,13 +323,14 @@ namespace mapnik
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
{
|
||||
character_info ci;
|
||||
unsigned c;
|
||||
|
||||
while (distance <= 0) {
|
||||
|
||||
while (distance <= 0)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
cur_node++;
|
||||
|
@ -332,7 +374,7 @@ namespace mapnik
|
|||
//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));
|
||||
|
@ -364,87 +406,26 @@ namespace mapnik
|
|||
|
||||
p->envelopes.push(e);
|
||||
|
||||
p->path.add_node(c, x - p->starting_x, -y + p->starting_y, (orientation == -1 ? angle + M_PI : angle));
|
||||
p->current_placement.path.add_node(c, x - p->current_placement.starting_x, -y + p->current_placement.starting_y, (orientation == -1 ? angle + M_PI : angle));
|
||||
|
||||
distance -= ci.width;
|
||||
}
|
||||
|
||||
p->placements.push_back(p->current_placement);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
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;
|
||||
|
||||
x = -string_width/2.0;
|
||||
y = -string_height/2.0 + 1.0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
{
|
||||
character_info ci;;
|
||||
ci = p->info->at(i);
|
||||
|
||||
unsigned c = ci.character;
|
||||
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
p->path.clear();
|
||||
|
||||
p->current_placement.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)
|
||||
|
@ -455,7 +436,7 @@ namespace mapnik
|
|||
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;
|
||||
|
@ -471,14 +452,14 @@ namespace mapnik
|
|||
double word_height = 0;
|
||||
for (unsigned int ii = 0; ii < p->info->num_characters(); ii++)
|
||||
{
|
||||
character_info ci;
|
||||
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;
|
||||
|
@ -511,42 +492,42 @@ namespace mapnik
|
|||
line_breaks.push_back(p->info->num_characters() + 1);
|
||||
line_widths.push_back(string_width);
|
||||
}
|
||||
|
||||
p->info->set_dimensions(string_width, string_height);
|
||||
|
||||
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;
|
||||
|
||||
p->current_placement.starting_x = starting_pos.first;
|
||||
p->current_placement.starting_y = starting_pos.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->geom->label_position(&p->starting_x, &p->starting_y);
|
||||
p->geom->label_position(&p->current_placement.starting_x, &p->current_placement.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);
|
||||
p->proj_trans->backward(p->current_placement.starting_x, p->current_placement.starting_y, z);
|
||||
p->ctrans->forward(&p->current_placement.starting_x, &p->current_placement.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;
|
||||
|
||||
x = -line_width/2.0;
|
||||
y = string_height/2.0;
|
||||
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
{
|
||||
character_info ci;
|
||||
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];
|
||||
|
@ -558,35 +539,31 @@ namespace mapnik
|
|||
}
|
||||
else
|
||||
{
|
||||
p->path.add_node(c, x, y, 0.0);
|
||||
|
||||
p->current_placement.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));
|
||||
e.init(p->current_placement.starting_x - (p->dimensions.first/2.0), p->current_placement.starting_y - (p->dimensions.second/2.0), p->current_placement.starting_x + (p->dimensions.first/2.0), p->current_placement.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);
|
||||
e.init(p->current_placement.starting_x + x, p->current_placement.starting_y - y, p->current_placement.starting_x + x + ci.width, p->current_placement.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;
|
||||
}
|
||||
p->placements.push_back(p->current_placement);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace mapnik
|
|||
size_(size),
|
||||
text_ratio_(0),
|
||||
wrap_width_(0),
|
||||
label_spacing_(0),
|
||||
fill_(fill),
|
||||
halo_fill_(Color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
|
@ -48,6 +49,7 @@ namespace mapnik
|
|||
size_(rhs.size_),
|
||||
text_ratio_(rhs.text_ratio_),
|
||||
wrap_width_(rhs.wrap_width_),
|
||||
label_spacing_(rhs.label_spacing_),
|
||||
fill_(rhs.fill_),
|
||||
halo_fill_(rhs.halo_fill_),
|
||||
halo_radius_(rhs.halo_radius_),
|
||||
|
@ -64,6 +66,7 @@ namespace mapnik
|
|||
size_ = other.size_;
|
||||
text_ratio_ = other.text_ratio_;
|
||||
wrap_width_ = other.wrap_width_;
|
||||
label_spacing_ = other.label_spacing_;
|
||||
fill_ = other.fill_;
|
||||
halo_fill_ = other.halo_fill_;
|
||||
halo_radius_ = other.halo_radius_;
|
||||
|
@ -85,7 +88,7 @@ namespace mapnik
|
|||
|
||||
unsigned text_symbolizer::get_text_ratio() const
|
||||
{
|
||||
return text_ratio_;
|
||||
return text_ratio_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_text_ratio(unsigned ratio)
|
||||
|
@ -95,12 +98,22 @@ namespace mapnik
|
|||
|
||||
unsigned text_symbolizer::get_wrap_width() const
|
||||
{
|
||||
return wrap_width_;
|
||||
return wrap_width_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_width(unsigned width)
|
||||
{
|
||||
wrap_width_ = width;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_label_spacing() const
|
||||
{
|
||||
return label_spacing_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_label_spacing(unsigned spacing)
|
||||
{
|
||||
label_spacing_ = spacing;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_text_size() const
|
||||
|
|
Loading…
Reference in a new issue