Patch from David Eastcott :
1. Modified Text Symbolizer a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur). b) adjusted vertical alignment calculation so that: i) middle -> has the center of the text line(s) at the point origin ii) bottom -> has the text line(s) below the point origin iii) top -> has the text line(s) above the point origin c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false allows line breaks at first wrap_char before wrap_width as an alternative to the original which was to create the line break at the first wrap_char after wrap_width d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle i) left -> has all text line(s) to left of the point origin ii) middle -> has all text line(s) centered on the the point origin iii) right -> has all text line(s) to the right of the point origin NOTE: dx, dy position adjustments are applied after alignments and before Justify. e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle i) left -> after alignments, has all text line(s) are left justified (left to right reading) ii) middle -> after alignments, has all text line(s) center justified iii) right -> after alignments, has all text line(s) right justified (right to left reading) f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping occurs. Line spacing is uniform and consistent and compensates for errors between text_size and the actual size (ci.height is inconsistent, depending on case and character); fixes issue with multi-line text where some lines have a slight gap and others are compressed together. 2. Modified shield_symbolizer a) added the attributes: i) allow_overlap ii) vertical_alignment iii) horizontal_alignment iv) justify_alignment v) wrap_width vi) wrap_character vii) wrap_before viii) text_convert ix) line_spacing x) character_spacing xi) opacity b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false i) false == image and text placement behaviour same as before ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes, dx/dy only affect text. Allows user to create point markers with text, but both the text and image rendering collision detection are done as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the other are omitted due to overlaps, but not both) c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry d) ensured that the text placement was not updating the detector unless a shield image was actually placed. e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used and no text is rendered over top of them.
This commit is contained in:
parent
df7bad25f9
commit
a3a5859466
11 changed files with 1106 additions and 726 deletions
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -60,7 +60,7 @@ extern "C"
|
|||
namespace mapnik
|
||||
{
|
||||
class font_face;
|
||||
|
||||
|
||||
typedef boost::shared_ptr<font_face> face_ptr;
|
||||
|
||||
class MAPNIK_DECL font_glyph : private boost::noncopyable
|
||||
|
@ -120,10 +120,10 @@ namespace mapnik
|
|||
{
|
||||
if (! FT_Set_Pixel_Sizes( face_, 0, size ))
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
~font_face()
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
@ -173,32 +173,32 @@ namespace mapnik
|
|||
FT_Matrix matrix;
|
||||
FT_Vector pen;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
|
||||
FT_BBox glyph_bbox;
|
||||
|
||||
FT_BBox glyph_bbox;
|
||||
FT_Glyph image;
|
||||
|
||||
glyph_ptr glyph = get_glyph(c);
|
||||
FT_Face face = glyph->get_face()->get_face();
|
||||
|
||||
matrix.xx = (FT_Fixed)( 1 * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)( 0 * 0x10000L );
|
||||
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
|
||||
matrix.xx = (FT_Fixed)( 1 * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)( 0 * 0x10000L );
|
||||
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
|
||||
matrix.yy = (FT_Fixed)( 1 * 0x10000L );
|
||||
|
||||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
return dimension_t(0, 0);
|
||||
|
||||
|
||||
error = FT_Get_Glyph(face->glyph, &image);
|
||||
if ( error )
|
||||
return dimension_t(0, 0);
|
||||
|
||||
FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
|
||||
FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
|
||||
FT_Done_Glyph(image);
|
||||
|
||||
unsigned tempx = face->glyph->advance.x >> 6;
|
||||
|
@ -208,7 +208,7 @@ namespace mapnik
|
|||
|
||||
return dimension_t(tempx, tempy);
|
||||
}
|
||||
|
||||
|
||||
void get_string_info(string_info & info)
|
||||
{
|
||||
unsigned width = 0;
|
||||
|
@ -217,17 +217,17 @@ namespace mapnik
|
|||
UnicodeString const& ustr = info.get_string();
|
||||
const UChar * text = ustr.getBuffer();
|
||||
UBiDi * bidi = ubidi_openSized(ustr.length(),0,&err);
|
||||
|
||||
|
||||
if (U_SUCCESS(err))
|
||||
{
|
||||
ubidi_setPara(bidi,text,ustr.length(), UBIDI_DEFAULT_LTR,0,&err);
|
||||
|
||||
|
||||
if (U_SUCCESS(err))
|
||||
{
|
||||
int32_t count = ubidi_countRuns(bidi,&err);
|
||||
int32_t logicalStart;
|
||||
int32_t length;
|
||||
|
||||
|
||||
for (int32_t i=0; i< count;++i)
|
||||
{
|
||||
if (UBIDI_LTR == ubidi_getVisualRun(bidi,i,&logicalStart,&length))
|
||||
|
@ -238,13 +238,13 @@ namespace mapnik
|
|||
info.add_info(ch, char_dim.first, char_dim.second);
|
||||
width += char_dim.first;
|
||||
height = char_dim.second > height ? char_dim.second : height;
|
||||
|
||||
|
||||
} while (--length > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
logicalStart += length;
|
||||
|
||||
|
||||
int32_t j=0,i=length;
|
||||
UnicodeString arabic;
|
||||
UChar * buf = arabic.getBuffer(length);
|
||||
|
@ -252,7 +252,7 @@ namespace mapnik
|
|||
UChar ch = text[--logicalStart];
|
||||
buf[j++] = ch;
|
||||
} while (--i > 0);
|
||||
|
||||
|
||||
arabic.releaseBuffer(length);
|
||||
if ( *arabic.getBuffer() >= 0x0600 && *arabic.getBuffer() <= 0x06ff)
|
||||
{
|
||||
|
@ -261,11 +261,11 @@ namespace mapnik
|
|||
U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
|
||||
U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
|
||||
,&err);
|
||||
|
||||
|
||||
shaped.releaseBuffer(arabic.length());
|
||||
|
||||
|
||||
if (U_SUCCESS(err))
|
||||
{
|
||||
{
|
||||
for (int j=0;j<shaped.length();++j)
|
||||
{
|
||||
dimension_t char_dim = character_dimensions(shaped[j]);
|
||||
|
@ -289,7 +289,7 @@ namespace mapnik
|
|||
}
|
||||
ubidi_close(bidi);
|
||||
}
|
||||
|
||||
|
||||
info.set_dimensions(width, height);
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ namespace mapnik
|
|||
private:
|
||||
std::vector<face_ptr> faces_;
|
||||
};
|
||||
|
||||
|
||||
typedef boost::shared_ptr<font_face_set> face_set_ptr;
|
||||
|
||||
class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>,
|
||||
|
@ -320,18 +320,18 @@ namespace mapnik
|
|||
FT_Library library_;
|
||||
static boost::mutex mutex_;
|
||||
static std::map<std::string,std::string> name2file_;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MAPNIK_DECL face_manager : private boost::noncopyable
|
||||
{
|
||||
typedef T font_engine_type;
|
||||
typedef std::map<std::string,face_ptr> faces;
|
||||
|
||||
|
||||
public:
|
||||
face_manager(T & engine)
|
||||
: engine_(engine) {}
|
||||
|
||||
|
||||
face_ptr get_face(std::string const& name)
|
||||
{
|
||||
typename faces::iterator itr;
|
||||
|
@ -395,44 +395,50 @@ namespace mapnik
|
|||
text_renderer (pixmap_type & pixmap, face_set_ptr faces)
|
||||
: pixmap_(pixmap),
|
||||
faces_(faces),
|
||||
fill_(0,0,0),
|
||||
fill_(0,0,0),
|
||||
halo_fill_(255,255,255),
|
||||
halo_radius_(0) {}
|
||||
halo_radius_(0),
|
||||
opacity_(1.0) {}
|
||||
|
||||
void set_pixel_size(unsigned size)
|
||||
{
|
||||
faces_->set_pixel_sizes(size);
|
||||
}
|
||||
|
||||
|
||||
void set_fill(mapnik::color const& fill)
|
||||
{
|
||||
fill_=fill;
|
||||
}
|
||||
|
||||
|
||||
void set_halo_fill(mapnik::color const& halo)
|
||||
{
|
||||
halo_fill_=halo;
|
||||
}
|
||||
|
||||
|
||||
void set_halo_radius( int radius=1)
|
||||
{
|
||||
halo_radius_=radius;
|
||||
}
|
||||
|
||||
void set_opacity( double opacity=1.0)
|
||||
{
|
||||
opacity_=opacity;
|
||||
}
|
||||
|
||||
Envelope<double> prepare_glyphs(text_path *path)
|
||||
{
|
||||
//clear glyphs
|
||||
glyphs_.clear();
|
||||
|
||||
|
||||
FT_Matrix matrix;
|
||||
FT_Vector pen;
|
||||
FT_Error error;
|
||||
|
||||
FT_BBox bbox;
|
||||
FT_BBox bbox;
|
||||
bbox.xMin = bbox.yMin = 32000; // Initialize these so we can tell if we
|
||||
bbox.xMax = bbox.yMax = -32000; // properly grew the bbox later
|
||||
|
||||
for (int i = 0; i < path->num_nodes(); i++)
|
||||
|
||||
for (int i = 0; i < path->num_nodes(); i++)
|
||||
{
|
||||
int c;
|
||||
double x, y, angle;
|
||||
|
@ -441,27 +447,27 @@ namespace mapnik
|
|||
|
||||
#ifdef MAPNIK_DEBUG
|
||||
// TODO Enable when we have support for setting verbosity
|
||||
//std::clog << "prepare_glyphs: " << c << "," << x <<
|
||||
//std::clog << "prepare_glyphs: " << c << "," << x <<
|
||||
// "," << y << "," << angle << std::endl;
|
||||
#endif
|
||||
|
||||
FT_BBox glyph_bbox;
|
||||
FT_BBox glyph_bbox;
|
||||
FT_Glyph image;
|
||||
|
||||
pen.x = int(x * 64);
|
||||
pen.y = int(y * 64);
|
||||
|
||||
|
||||
glyph_ptr glyph = faces_->get_glyph(unsigned(c));
|
||||
FT_Face face = glyph->get_face()->get_face();
|
||||
|
||||
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
||||
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
|
||||
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
||||
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
|
||||
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
continue;
|
||||
|
||||
|
@ -469,23 +475,23 @@ namespace mapnik
|
|||
if ( error )
|
||||
continue;
|
||||
|
||||
FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox);
|
||||
if (glyph_bbox.xMin < bbox.xMin)
|
||||
bbox.xMin = glyph_bbox.xMin;
|
||||
if (glyph_bbox.yMin < bbox.yMin)
|
||||
bbox.yMin = glyph_bbox.yMin;
|
||||
if (glyph_bbox.xMax > bbox.xMax)
|
||||
bbox.xMax = glyph_bbox.xMax;
|
||||
if (glyph_bbox.yMax > bbox.yMax)
|
||||
FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox);
|
||||
if (glyph_bbox.xMin < bbox.xMin)
|
||||
bbox.xMin = glyph_bbox.xMin;
|
||||
if (glyph_bbox.yMin < bbox.yMin)
|
||||
bbox.yMin = glyph_bbox.yMin;
|
||||
if (glyph_bbox.xMax > bbox.xMax)
|
||||
bbox.xMax = glyph_bbox.xMax;
|
||||
if (glyph_bbox.yMax > bbox.yMax)
|
||||
bbox.yMax = glyph_bbox.yMax;
|
||||
|
||||
// Check if we properly grew the bbox
|
||||
if ( bbox.xMin > bbox.xMax )
|
||||
{
|
||||
bbox.xMin = 0;
|
||||
bbox.yMin = 0;
|
||||
bbox.xMax = 0;
|
||||
bbox.yMax = 0;
|
||||
bbox.xMin = 0;
|
||||
bbox.yMin = 0;
|
||||
bbox.xMax = 0;
|
||||
bbox.yMax = 0;
|
||||
}
|
||||
|
||||
// take ownership of the glyph
|
||||
|
@ -494,23 +500,23 @@ namespace mapnik
|
|||
|
||||
return Envelope<double>(bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax);
|
||||
}
|
||||
|
||||
|
||||
void render(double x0, double y0)
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Vector start;
|
||||
unsigned height = pixmap_.height();
|
||||
|
||||
start.x = static_cast<FT_Pos>(x0 * (1 << 6));
|
||||
start.x = static_cast<FT_Pos>(x0 * (1 << 6));
|
||||
start.y = static_cast<FT_Pos>((height - y0) * (1 << 6));
|
||||
|
||||
// now render transformed glyphs
|
||||
typename glyphs_t::iterator pos;
|
||||
|
||||
|
||||
//make sure we've got reasonable values.
|
||||
if (halo_radius_ > 0 && halo_radius_ < 256)
|
||||
{
|
||||
//render halo
|
||||
//render halo
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph_Transform(pos->image,0,&start);
|
||||
|
@ -520,11 +526,11 @@ namespace mapnik
|
|||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)pos->image;
|
||||
render_halo(&bit->bitmap, halo_fill_.rgba(),
|
||||
render_halo(&bit->bitmap, halo_fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top,halo_radius_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//render actual text
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
|
@ -537,15 +543,15 @@ namespace mapnik
|
|||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)pos->image;
|
||||
render_bitmap(&bit->bitmap, fill_.rgba(),
|
||||
render_bitmap(&bit->bitmap, fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void render_halo(FT_Bitmap *bitmap,unsigned rgba,int x,int y,int radius)
|
||||
{
|
||||
int x_max=x+bitmap->width;
|
||||
|
@ -561,7 +567,7 @@ namespace mapnik
|
|||
{
|
||||
for (int n=-halo_radius_; n <=halo_radius_; ++n)
|
||||
for (int m=-halo_radius_;m <= halo_radius_; ++m)
|
||||
pixmap_.blendPixel(i+m,j+n,rgba,gray);
|
||||
pixmap_.blendPixel2(i+m,j+n,rgba,gray,opacity_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -580,12 +586,12 @@ namespace mapnik
|
|||
int gray=bitmap->buffer[q*bitmap->width+p];
|
||||
if (gray)
|
||||
{
|
||||
pixmap_.blendPixel(i,j,rgba,gray);
|
||||
pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pixmap_type & pixmap_;
|
||||
face_set_ptr faces_;
|
||||
mapnik::color fill_;
|
||||
|
@ -594,7 +600,8 @@ namespace mapnik
|
|||
unsigned text_ratio_;
|
||||
unsigned wrap_width_;
|
||||
glyphs_t glyphs_;
|
||||
};
|
||||
double opacity_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // FONT_ENGINE_FREETYPE_HPP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -42,7 +42,7 @@
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
|
||||
struct Multiply
|
||||
{
|
||||
inline static void mergeRGB(unsigned const &r0, unsigned const &g0, unsigned const &b0,
|
||||
|
@ -132,7 +132,7 @@ namespace mapnik
|
|||
if (b1>255) b1=255;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MAPNIK_DECL Image32
|
||||
{
|
||||
private:
|
||||
|
@ -148,31 +148,31 @@ namespace mapnik
|
|||
#endif
|
||||
~Image32();
|
||||
void setBackground(color const& background);
|
||||
const color& getBackground() const;
|
||||
const color& getBackground() const;
|
||||
const ImageData32& data() const;
|
||||
|
||||
inline ImageData32& data()
|
||||
|
||||
inline ImageData32& data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
inline const unsigned char* raw_data() const
|
||||
{
|
||||
return data_.getBytes();
|
||||
}
|
||||
|
||||
|
||||
inline unsigned char* raw_data()
|
||||
{
|
||||
return data_.getBytes();
|
||||
}
|
||||
|
||||
|
||||
inline image_view<ImageData32> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
|
||||
{
|
||||
return image_view<ImageData32>(x,y,w,h,data_);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
inline bool checkBounds(unsigned x, unsigned y) const
|
||||
{
|
||||
return (x < width_ && y < height_);
|
||||
|
@ -187,24 +187,29 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
inline void blendPixel(int x,int y,unsigned int rgba1,int t)
|
||||
{
|
||||
blendPixel2(x,y,rgba1,t,1.0); // do not change opacity
|
||||
}
|
||||
|
||||
inline void blendPixel2(int x,int y,unsigned int rgba1,int t,double opacity)
|
||||
{
|
||||
if (checkBounds(x,y))
|
||||
{
|
||||
unsigned rgba0 = data_(x,y);
|
||||
unsigned a1 = (rgba1 >> 24) & 0xff; //t;
|
||||
unsigned rgba0 = data_(x,y);
|
||||
unsigned a1 = (int)(((rgba1 >> 24) & 0xff) * opacity) & 0xff; // adjust for desired opacity
|
||||
a1 = (t*a1) / 255;
|
||||
if (a1 == 0) return;
|
||||
unsigned r1 = rgba1 & 0xff;
|
||||
unsigned g1 = (rgba1 >> 8 ) & 0xff;
|
||||
unsigned b1 = (rgba1 >> 16) & 0xff;
|
||||
|
||||
|
||||
unsigned a0 = (rgba0 >> 24) & 0xff;
|
||||
unsigned r0 = (rgba0 & 0xff) * a0;
|
||||
unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
|
||||
unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;
|
||||
|
||||
|
||||
a0 = ((a1 + a0) << 8) - a0*a1;
|
||||
|
||||
|
||||
r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
|
||||
g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
|
||||
b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
|
||||
|
@ -217,7 +222,7 @@ namespace mapnik
|
|||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned height() const
|
||||
{
|
||||
return height_;
|
||||
|
@ -225,36 +230,36 @@ namespace mapnik
|
|||
|
||||
inline void set_rectangle(int x0,int y0,ImageData32 const& data)
|
||||
{
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext1(x0,y0,x0+data.width(),y0+data.height());
|
||||
|
||||
|
||||
if (ext0.intersects(ext1))
|
||||
{
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
for (int y = box.miny(); y < box.maxy(); ++y)
|
||||
{
|
||||
unsigned int* row_to = data_.getRow(y);
|
||||
unsigned int const * row_from = data.getRow(y-y0);
|
||||
|
||||
|
||||
for (int x = box.minx(); x < box.maxx(); ++x)
|
||||
{
|
||||
if (row_from[x-x0] & 0xff000000)
|
||||
{
|
||||
row_to[x] = row_from[x-x0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void set_rectangle_alpha(int x0,int y0,const ImageData32& data)
|
||||
{
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
|
||||
|
||||
|
||||
if (ext0.intersects(ext1))
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
for (int y = box.miny(); y < box.maxy(); ++y)
|
||||
{
|
||||
unsigned int* row_to = data_.getRow(y);
|
||||
|
@ -263,20 +268,20 @@ namespace mapnik
|
|||
{
|
||||
unsigned rgba0 = row_to[x];
|
||||
unsigned rgba1 = row_from[x-x0];
|
||||
|
||||
|
||||
unsigned a1 = (rgba1 >> 24) & 0xff;
|
||||
if (a1 == 0) continue;
|
||||
unsigned r1 = rgba1 & 0xff;
|
||||
unsigned g1 = (rgba1 >> 8 ) & 0xff;
|
||||
unsigned b1 = (rgba1 >> 16) & 0xff;
|
||||
|
||||
|
||||
unsigned a0 = (rgba0 >> 24) & 0xff;
|
||||
unsigned r0 = (rgba0 & 0xff) * a0;
|
||||
unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
|
||||
unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;
|
||||
|
||||
|
||||
a0 = ((a1 + a0) << 8) - a0*a1;
|
||||
|
||||
|
||||
r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
|
||||
g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
|
||||
b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
|
||||
|
@ -286,15 +291,15 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void set_rectangle_alpha2(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
|
||||
{
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
|
||||
|
||||
|
||||
if (ext0.intersects(ext1))
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
for (int y = box.miny(); y < box.maxy(); ++y)
|
||||
{
|
||||
unsigned int* row_to = data_.getRow(y);
|
||||
|
@ -308,24 +313,24 @@ namespace mapnik
|
|||
unsigned r1 = rgba1 & 0xff;
|
||||
unsigned g1 = (rgba1 >> 8 ) & 0xff;
|
||||
unsigned b1 = (rgba1 >> 16) & 0xff;
|
||||
|
||||
|
||||
unsigned a0 = (rgba0 >> 24) & 0xff;
|
||||
unsigned r0 = rgba0 & 0xff ;
|
||||
unsigned g0 = (rgba0 >> 8 ) & 0xff;
|
||||
unsigned b0 = (rgba0 >> 16) & 0xff;
|
||||
|
||||
|
||||
unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;
|
||||
|
||||
|
||||
r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
|
||||
g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
|
||||
b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;
|
||||
|
||||
|
||||
row_to[x] = (a << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename MergeMethod>
|
||||
inline void merge_rectangle(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -38,26 +38,27 @@
|
|||
namespace mapnik
|
||||
{
|
||||
typedef text_path placement_element;
|
||||
|
||||
|
||||
struct placement : boost::noncopyable
|
||||
{
|
||||
{
|
||||
placement(string_info & info_, shield_symbolizer const& sym, bool has_dimensions_= false);
|
||||
|
||||
|
||||
placement(string_info & info_, text_symbolizer const& sym);
|
||||
|
||||
|
||||
~placement();
|
||||
|
||||
|
||||
string_info & info;
|
||||
|
||||
|
||||
position displacement_;
|
||||
label_placement_e label_placement;
|
||||
|
||||
std::queue< Envelope<double> > envelopes;
|
||||
|
||||
|
||||
//output
|
||||
boost::ptr_vector<placement_element> placements;
|
||||
|
||||
|
||||
int wrap_width;
|
||||
bool wrap_before; // wraps text at wrap_char immediately before current word
|
||||
unsigned char wrap_char;
|
||||
int text_ratio;
|
||||
|
||||
|
@ -71,34 +72,35 @@ namespace mapnik
|
|||
bool has_dimensions;
|
||||
bool allow_overlap;
|
||||
std::pair<double, double> dimensions;
|
||||
int text_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
class placement_finder : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
placement_finder(DetectorT & detector);
|
||||
|
||||
|
||||
//Try place a single label at the given point
|
||||
void find_point_placement(placement & p, double pos_x, double pos_y, vertical_alignment_e = MIDDLE, unsigned line_spacing=0, unsigned character_spacing=0);
|
||||
|
||||
void find_point_placement(placement & p, double pos_x, double pos_y, vertical_alignment_e = 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>
|
||||
void find_point_placements(placement & p, T & path);
|
||||
|
||||
|
||||
//Iterate over the given path, placing line-following labels with respect to label_spacing
|
||||
template <typename T>
|
||||
void find_line_placements(placement & p, T & path);
|
||||
|
||||
|
||||
void update_detector(placement & p);
|
||||
|
||||
|
||||
void clear();
|
||||
|
||||
|
||||
private:
|
||||
///Helpers for find_line_placement
|
||||
|
||||
|
||||
///Returns a possible placement on the given line, does not test for collisions
|
||||
//index: index of the node the current line ends on
|
||||
//distance: distance along the given index that the placement should start at, this includes the offset,
|
||||
|
@ -107,33 +109,33 @@ namespace mapnik
|
|||
// otherwise it will autodetect the orientation.
|
||||
// If >= 50% of the characters end up upside down, it will be retried the other way.
|
||||
// RETURN: 1/-1 depending which way up the string ends up being.
|
||||
std::auto_ptr<placement_element> get_placement_offset(placement & p,
|
||||
const std::vector<vertex2d> & path_positions,
|
||||
const std::vector<double> & path_distances,
|
||||
std::auto_ptr<placement_element> get_placement_offset(placement & p,
|
||||
const std::vector<vertex2d> & path_positions,
|
||||
const std::vector<double> & path_distances,
|
||||
int & orientation, unsigned index, double distance);
|
||||
|
||||
|
||||
///Tests wether the given placement_element be placed without a collision
|
||||
// Returns true if it can
|
||||
// NOTE: This edits p.envelopes so it can be used afterwards (you must clear it otherwise)
|
||||
bool test_placement(placement & p, const std::auto_ptr<placement_element> & current_placement, const int & orientation);
|
||||
|
||||
|
||||
///Does a line-circle intersect calculation
|
||||
// NOTE: Follow the strict pre conditions
|
||||
// Pre Conditions: x1,y1 is within radius distance of cx,cy. x2,y2 is outside radius distance of cx,cy
|
||||
// This means there is exactly one intersect point
|
||||
// Result is returned in ix, iy
|
||||
void find_line_circle_intersection(
|
||||
const double &cx, const double &cy, const double &radius,
|
||||
const double &x1, const double &y1, const double &x2, const double &y2,
|
||||
const double &cx, const double &cy, const double &radius,
|
||||
const double &x1, const double &y1, const double &x2, const double &y2,
|
||||
double &ix, double &iy);
|
||||
|
||||
|
||||
///General Internals
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DetectorT & detector_;
|
||||
Envelope<double> const& dimensions_;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -25,30 +25,40 @@
|
|||
#ifndef SHIELD_SYMBOLIZER_HPP
|
||||
#define SHIELD_SYMBOLIZER_HPP
|
||||
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/text_symbolizer.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
namespace mapnik
|
||||
{
|
||||
struct MAPNIK_DECL shield_symbolizer : public text_symbolizer,
|
||||
public symbolizer_with_image
|
||||
{
|
||||
{
|
||||
shield_symbolizer(std::string const& name,
|
||||
std::string const& face_name,
|
||||
unsigned size,
|
||||
color const& fill,
|
||||
color const& fill,
|
||||
std::string const& file,
|
||||
std::string const& type,
|
||||
unsigned width,unsigned height);
|
||||
shield_symbolizer(std::string const& name,
|
||||
unsigned size,
|
||||
color const& fill,
|
||||
color const& fill,
|
||||
std::string const& file,
|
||||
std::string const& type,
|
||||
unsigned width,unsigned height);
|
||||
|
||||
bool get_unlock_image() const; // image is not locked to the text placement
|
||||
void set_unlock_image(bool unlock_image);
|
||||
bool get_no_text() const; // do no render text
|
||||
void set_no_text(bool unlock_image);
|
||||
|
||||
private:
|
||||
|
||||
bool unlock_image_;
|
||||
bool no_text_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -40,11 +40,12 @@ namespace mapnik
|
|||
enum label_placement_enum {
|
||||
POINT_PLACEMENT,
|
||||
LINE_PLACEMENT,
|
||||
VERTEX_PLACEMENT,
|
||||
label_placement_enum_MAX
|
||||
};
|
||||
|
||||
|
||||
DEFINE_ENUM( label_placement_e, label_placement_enum );
|
||||
|
||||
|
||||
enum vertical_alignment
|
||||
{
|
||||
TOP = 0,
|
||||
|
@ -55,6 +56,26 @@ namespace mapnik
|
|||
|
||||
DEFINE_ENUM( vertical_alignment_e, vertical_alignment );
|
||||
|
||||
enum horizontal_alignment
|
||||
{
|
||||
H_LEFT = 0,
|
||||
H_MIDDLE,
|
||||
H_RIGHT,
|
||||
horizontal_alignment_MAX
|
||||
};
|
||||
|
||||
DEFINE_ENUM( horizontal_alignment_e, horizontal_alignment );
|
||||
|
||||
enum justify_alignment
|
||||
{
|
||||
J_LEFT = 0,
|
||||
J_MIDDLE,
|
||||
J_RIGHT,
|
||||
justify_alignment_MAX
|
||||
};
|
||||
|
||||
DEFINE_ENUM( justify_alignment_e, justify_alignment );
|
||||
|
||||
enum text_convert
|
||||
{
|
||||
NONE = 0,
|
||||
|
@ -66,12 +87,12 @@ namespace mapnik
|
|||
DEFINE_ENUM( text_convert_e, text_convert );
|
||||
|
||||
typedef boost::tuple<double,double> position;
|
||||
|
||||
|
||||
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, unsigned size, color const& fill);
|
||||
{
|
||||
text_symbolizer(std::string const& name,std::string const& face_name,
|
||||
unsigned size, color const& fill);
|
||||
text_symbolizer(std::string const& 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;
|
||||
|
@ -114,8 +135,8 @@ namespace mapnik
|
|||
label_placement_e get_label_placement() const;
|
||||
void set_vertical_alignment(vertical_alignment_e valign);
|
||||
vertical_alignment_e get_vertical_alignment() const;
|
||||
void set_anchor(double x, double y);
|
||||
position const& get_anchor() const;
|
||||
void set_anchor(double x, double y);
|
||||
position const& get_anchor() const;
|
||||
void set_displacement(double x, double y);
|
||||
position const& get_displacement() const;
|
||||
void set_avoid_edges(bool avoid);
|
||||
|
@ -124,6 +145,15 @@ namespace mapnik
|
|||
double get_minimum_distance() const;
|
||||
void set_allow_overlap(bool overlap);
|
||||
bool get_allow_overlap() const;
|
||||
void set_opacity(double opacity);
|
||||
double get_opacity() const;
|
||||
bool get_wrap_before() const; // wrap text at wrap_char immediately before current work
|
||||
void set_wrap_before(bool wrap_before);
|
||||
void set_horizontal_alignment(horizontal_alignment_e valign);
|
||||
horizontal_alignment_e get_horizontal_alignment() const;
|
||||
void set_justify_alignment(justify_alignment_e valign);
|
||||
justify_alignment_e get_justify_alignment() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string face_name_;
|
||||
|
@ -149,6 +179,10 @@ namespace mapnik
|
|||
bool avoid_edges_;
|
||||
double minimum_distance_;
|
||||
bool overlap_;
|
||||
double opacity_;
|
||||
bool wrap_before_;
|
||||
horizontal_alignment_e halign_;
|
||||
justify_alignment_e jalign_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -74,14 +74,14 @@
|
|||
#include <iostream>
|
||||
#endif
|
||||
|
||||
namespace mapnik
|
||||
namespace mapnik
|
||||
{
|
||||
class pattern_source : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
pattern_source(ImageData32 const& pattern)
|
||||
: pattern_(pattern) {}
|
||||
|
||||
|
||||
unsigned int width() const
|
||||
{
|
||||
return pattern_.width();
|
||||
|
@ -93,17 +93,17 @@ namespace mapnik
|
|||
agg::rgba8 pixel(int x, int y) const
|
||||
{
|
||||
unsigned c = pattern_(x,y);
|
||||
return agg::rgba8(c & 0xff,
|
||||
(c >> 8) & 0xff,
|
||||
return agg::rgba8(c & 0xff,
|
||||
(c >> 8) & 0xff,
|
||||
(c >> 16) & 0xff,
|
||||
(c >> 24) & 0xff);
|
||||
}
|
||||
private:
|
||||
ImageData32 const& pattern_;
|
||||
};
|
||||
|
||||
|
||||
struct rasterizer : agg::rasterizer_scanline_aa<>, boost::noncopyable {};
|
||||
|
||||
|
||||
template <typename T>
|
||||
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<agg_renderer>(m),
|
||||
|
@ -122,7 +122,7 @@ namespace mapnik
|
|||
std::clog << "scale=" << m.scale() << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
agg_renderer<T>::~agg_renderer() {}
|
||||
|
||||
|
@ -130,7 +130,7 @@ namespace mapnik
|
|||
void agg_renderer<T>::start_map_processing(Map const& map)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "start map processing bbox="
|
||||
std::clog << "start map processing bbox="
|
||||
<< map.getCurrentExtent() << "\n";
|
||||
#endif
|
||||
ras_ptr->clip_box(0,0,width_,height_);
|
||||
|
@ -143,20 +143,20 @@ namespace mapnik
|
|||
std::clog << "end map processing\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::start_layer_processing(Layer const& lay)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "start layer processing : " << lay.name() << "\n";
|
||||
std::clog << "datasource = " << lay.datasource().get() << "\n";
|
||||
#endif
|
||||
#endif
|
||||
if (lay.clear_label_cache())
|
||||
{
|
||||
detector_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::end_layer_processing(Layer const&)
|
||||
{
|
||||
|
@ -164,35 +164,35 @@ namespace mapnik
|
|||
std::clog << "end layer processing\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
|
||||
|
||||
color const& fill_ = sym.get_fill();
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
unsigned r=fill_.red();
|
||||
unsigned g=fill_.green();
|
||||
unsigned b=fill_.blue();
|
||||
unsigned a=fill_.alpha();
|
||||
renderer ren(renb);
|
||||
|
||||
|
||||
ras_ptr->reset();
|
||||
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom=feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
|
@ -201,45 +201,45 @@ namespace mapnik
|
|||
ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity())));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
}
|
||||
|
||||
|
||||
typedef boost::tuple<double,double,double,double> segment_t;
|
||||
bool y_order(segment_t const& first,segment_t const& second)
|
||||
{
|
||||
double miny0 = std::min(first.get<1>(),first.get<3>());
|
||||
double miny1 = std::min(second.get<1>(),second.get<3>());
|
||||
double miny1 = std::min(second.get<1>(),second.get<3>());
|
||||
return miny0 > miny1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(building_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef coord_transform3<CoordTransform,geometry2d> path_type_roof;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
|
||||
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
ren_base renb(pixf);
|
||||
|
||||
|
||||
color const& fill_ = sym.get_fill();
|
||||
unsigned r=fill_.red();
|
||||
unsigned g=fill_.green();
|
||||
unsigned b=fill_.blue();
|
||||
unsigned a=fill_.alpha();
|
||||
renderer ren(renb);
|
||||
renderer ren(renb);
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
|
||||
ras_ptr->reset();
|
||||
double height = 0.7071 * sym.height(); // height in meters
|
||||
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
boost::scoped_ptr<geometry2d> frame(new line_string_impl);
|
||||
boost::scoped_ptr<geometry2d> roof(new polygon_impl);
|
||||
std::deque<segment_t> face_segments;
|
||||
|
@ -262,7 +262,7 @@ namespace mapnik
|
|||
{
|
||||
face_segments.push_back(segment_t(x0,y0,x,y));
|
||||
}
|
||||
x0 = x;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
std::sort(face_segments.begin(),face_segments.end(), y_order);
|
||||
|
@ -274,17 +274,17 @@ namespace mapnik
|
|||
faces->line_to(itr->get<2>(),itr->get<3>());
|
||||
faces->line_to(itr->get<2>(),itr->get<3>() + height);
|
||||
faces->line_to(itr->get<0>(),itr->get<1>() + height);
|
||||
|
||||
|
||||
path_type faces_path (t_,*faces,prj_trans);
|
||||
ras_ptr->add_path(faces_path);
|
||||
ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity())));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
ras_ptr->reset();
|
||||
|
||||
|
||||
frame->move_to(itr->get<0>(),itr->get<1>());
|
||||
frame->line_to(itr->get<0>(),itr->get<1>()+height);
|
||||
frame->line_to(itr->get<0>(),itr->get<1>()+height);
|
||||
}
|
||||
|
||||
|
||||
geom.rewind(0);
|
||||
for (unsigned j=0;j<geom.num_points();++j)
|
||||
{
|
||||
|
@ -300,14 +300,14 @@ namespace mapnik
|
|||
frame->line_to(x,y+height);
|
||||
roof->line_to(x,y+height);
|
||||
}
|
||||
}
|
||||
path_type path(t_,*frame,prj_trans);
|
||||
}
|
||||
path_type path(t_,*frame,prj_trans);
|
||||
agg::conv_stroke<path_type> stroke(path);
|
||||
ras_ptr->add_path(stroke);
|
||||
ren.color(agg::rgba8(128, 128, 128, int(255 * sym.get_opacity())));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
ras_ptr->reset();
|
||||
|
||||
|
||||
path_type roof_path (t_,*roof,prj_trans);
|
||||
ras_ptr->add_path(roof_path);
|
||||
ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity())));
|
||||
|
@ -320,17 +320,17 @@ namespace mapnik
|
|||
void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
{
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef agg::renderer_outline_aa<ren_base> renderer_oaa;
|
||||
typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
mapnik::stroke const& stroke_ = sym.get_stroke();
|
||||
color const& col = stroke_.get_color();
|
||||
unsigned r=col.red();
|
||||
|
@ -340,72 +340,72 @@ namespace mapnik
|
|||
renderer ren(renb);
|
||||
ras_ptr->reset();
|
||||
agg::scanline_p8 sl;
|
||||
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 1)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
|
||||
if (stroke_.has_dash())
|
||||
{
|
||||
{
|
||||
agg::conv_dash<path_type> dash(path);
|
||||
dash_array const& d = stroke_.get_dash_array();
|
||||
dash_array::const_iterator itr = d.begin();
|
||||
dash_array::const_iterator end = d.end();
|
||||
for (;itr != end;++itr)
|
||||
{
|
||||
dash.add_dash(itr->first, itr->second);
|
||||
dash.add_dash(itr->first, itr->second);
|
||||
}
|
||||
|
||||
|
||||
agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
|
||||
|
||||
|
||||
line_join_e join=stroke_.get_line_join();
|
||||
if ( join == MITER_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == ROUND_JOIN)
|
||||
else if( join == ROUND_JOIN)
|
||||
stroke.generator().line_join(agg::round_join);
|
||||
else
|
||||
stroke.generator().line_join(agg::bevel_join);
|
||||
|
||||
|
||||
line_cap_e cap=stroke_.get_line_cap();
|
||||
if (cap == BUTT_CAP)
|
||||
if (cap == BUTT_CAP)
|
||||
stroke.generator().line_cap(agg::butt_cap);
|
||||
else if (cap == SQUARE_CAP)
|
||||
stroke.generator().line_cap(agg::square_cap);
|
||||
else
|
||||
else
|
||||
stroke.generator().line_cap(agg::round_cap);
|
||||
|
||||
|
||||
stroke.generator().miter_limit(4.0);
|
||||
stroke.generator().width(stroke_.get_width());
|
||||
|
||||
|
||||
ras_ptr->add_path(stroke);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
agg::conv_stroke<path_type> stroke(path);
|
||||
line_join_e join=stroke_.get_line_join();
|
||||
if ( join == MITER_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == ROUND_JOIN)
|
||||
else if( join == ROUND_JOIN)
|
||||
stroke.generator().line_join(agg::round_join);
|
||||
else
|
||||
stroke.generator().line_join(agg::bevel_join);
|
||||
|
||||
|
||||
line_cap_e cap=stroke_.get_line_cap();
|
||||
if (cap == BUTT_CAP)
|
||||
if (cap == BUTT_CAP)
|
||||
stroke.generator().line_cap(agg::butt_cap);
|
||||
else if (cap == SQUARE_CAP)
|
||||
stroke.generator().line_cap(agg::square_cap);
|
||||
else
|
||||
else
|
||||
stroke.generator().line_cap(agg::round_cap);
|
||||
|
||||
|
||||
stroke.generator().miter_limit(4.0);
|
||||
stroke.generator().width(stroke_.get_width());
|
||||
ras_ptr->add_path(stroke);
|
||||
|
@ -415,7 +415,7 @@ namespace mapnik
|
|||
ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity())));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(point_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
|
@ -430,7 +430,7 @@ namespace mapnik
|
|||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
|
||||
|
||||
geom.label_position(&x,&y);
|
||||
prj_trans.backward(x,y,z);
|
||||
t_.forward(&x,&y);
|
||||
|
@ -442,23 +442,37 @@ namespace mapnik
|
|||
floor(y - 0.5 * h),
|
||||
ceil (x + 0.5 * w),
|
||||
ceil (y + 0.5 * h));
|
||||
if (sym.get_allow_overlap() ||
|
||||
if (sym.get_allow_overlap() ||
|
||||
detector_.has_placement(label_ext))
|
||||
{
|
||||
{
|
||||
pixmap_.set_rectangle_alpha2(*data,px,py,sym.get_opacity());
|
||||
detector_.insert(label_ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(shield_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
UnicodeString text = feature[sym.get_name()].to_unicode();
|
||||
|
||||
UnicodeString text;
|
||||
if( sym.get_no_text() )
|
||||
text = UnicodeString( " " ); // use 'space' as the text to render
|
||||
else
|
||||
text = feature[sym.get_name()].to_unicode(); // use text from feature to render
|
||||
|
||||
if ( sym.get_text_convert() == TOUPPER)
|
||||
{
|
||||
text = text.toUpper();
|
||||
}
|
||||
else if ( sym.get_text_convert() == TOLOWER)
|
||||
{
|
||||
text = text.toLower();
|
||||
}
|
||||
boost::shared_ptr<ImageData32> const& data = sym.get_image();
|
||||
if (text.length() > 0 && data)
|
||||
{
|
||||
|
@ -468,7 +482,7 @@ namespace mapnik
|
|||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
@ -476,83 +490,110 @@ namespace mapnik
|
|||
if (faces->size() > 0)
|
||||
{
|
||||
text_renderer<T> ren(pixmap_, faces);
|
||||
|
||||
|
||||
ren.set_pixel_size(sym.get_text_size());
|
||||
ren.set_fill(sym.get_fill());
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius());
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
|
||||
string_info info(text);
|
||||
|
||||
|
||||
faces->get_string_info(info);
|
||||
|
||||
|
||||
|
||||
int w = data->width();
|
||||
int h = data->height();
|
||||
|
||||
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0;i<num_geom;++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 0 )
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 0 )
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
{
|
||||
double label_x;
|
||||
double label_y;
|
||||
double z=0.0;
|
||||
placement text_placement(info, sym, false);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
geom.label_position(&label_x, &label_y);
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
finder.find_point_placement(text_placement,label_x,label_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;
|
||||
// remove displacement from image label
|
||||
position pos = sym.get_displacement();
|
||||
double lx = x - boost::get<0>(pos);
|
||||
double ly = y - boost::get<1>(pos);
|
||||
int px=int(lx - (0.5 * w)) ;
|
||||
int py=int(ly - (0.5 * h)) ;
|
||||
Envelope<double> label_ext (floor(lx - 0.5 * w), floor(ly - 0.5 * h), ceil (lx + 0.5 * w), ceil (ly + 0.5 * h));
|
||||
|
||||
if ( detector_.has_placement(label_ext))
|
||||
{
|
||||
pixmap_.set_rectangle_alpha(px,py,*data);
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.render(x,y);
|
||||
detector_.insert(label_ext);
|
||||
label_placement_enum how_placed = sym.get_label_placement();
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT)
|
||||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
for( unsigned jj = 0; jj < geom.num_points(); jj++ )
|
||||
{
|
||||
double label_x;
|
||||
double label_y;
|
||||
double z=0.0;
|
||||
placement text_placement(info, sym, false);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
text_placement.allow_overlap = sym.get_allow_overlap();
|
||||
if( how_placed == VERTEX_PLACEMENT )
|
||||
geom.vertex(&label_x,&label_y); // by vertex
|
||||
else
|
||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
|
||||
finder.find_point_placement( text_placement,label_x,label_y,sym.get_vertical_alignment(),sym.get_line_spacing(),
|
||||
sym.get_character_spacing(),sym.get_horizontal_alignment(),sym.get_justify_alignment() );
|
||||
|
||||
// check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies
|
||||
if( text_placement.placements.size() > 0)
|
||||
{
|
||||
double x = text_placement.placements[0].starting_x;
|
||||
double y = text_placement.placements[0].starting_y;
|
||||
int px;
|
||||
int py;
|
||||
Envelope<double> label_ext;
|
||||
|
||||
if( !sym.get_unlock_image() )
|
||||
{ // center image at text center position
|
||||
// remove displacement from image label
|
||||
position pos = sym.get_displacement();
|
||||
double lx = x - boost::get<0>(pos);
|
||||
double ly = y - boost::get<1>(pos);
|
||||
px=int(floor(lx - (0.5 * w))) ;
|
||||
py=int(floor(ly - (0.5 * h))) ;
|
||||
label_ext.init( floor(lx - 0.5 * w), floor(ly - 0.5 * h), ceil (lx + 0.5 * w), ceil (ly + 0.5 * h) );
|
||||
}
|
||||
else
|
||||
{ // center image at reference location
|
||||
px=int(floor(label_x - 0.5 * w));
|
||||
py=int(floor(label_y - 0.5 * h));
|
||||
label_ext.init( floor(label_x - 0.5 * w), floor(label_y - 0.5 * h), ceil (label_x + 0.5 * w), ceil (label_y + 0.5 * h));
|
||||
}
|
||||
|
||||
if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) )
|
||||
{
|
||||
//pixmap_.set_rectangle_alpha(px,py,*data);
|
||||
pixmap_.set_rectangle_alpha2(*data,px,py,sym.get_opacity());
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[0]);
|
||||
ren.render(x,y);
|
||||
detector_.insert(label_ext);
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
|
||||
else if (geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT)
|
||||
|
||||
else if (geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT)
|
||||
{
|
||||
placement text_placement(info, sym, true);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
finder.find_point_placements<path_type>(text_placement,path);
|
||||
|
||||
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
|
||||
{
|
||||
int w = data->width();
|
||||
int h = data->height();
|
||||
int h = data->height();
|
||||
double x = text_placement.placements[ii].starting_x;
|
||||
double y = text_placement.placements[ii].starting_y;
|
||||
|
||||
|
||||
int px=int(x - (w/2));
|
||||
int py=int(y - (h/2));
|
||||
|
||||
|
||||
pixmap_.set_rectangle_alpha(px,py,*data);
|
||||
|
||||
|
||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.render(x,y);
|
||||
}
|
||||
|
@ -563,7 +604,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
|
@ -574,68 +615,68 @@ namespace mapnik
|
|||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
|
||||
typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
|
||||
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
|
||||
|
||||
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
|
||||
|
||||
ImageData32 pat = * sym.get_image();
|
||||
renderer_base ren_base(pixf);
|
||||
agg::pattern_filter_bilinear_rgba8 filter;
|
||||
renderer_base ren_base(pixf);
|
||||
agg::pattern_filter_bilinear_rgba8 filter;
|
||||
pattern_source source(pat);
|
||||
pattern_type pattern (filter,source);
|
||||
renderer_type ren(ren_base, pattern);
|
||||
ren.clip_box(0,0,width_,height_);
|
||||
rasterizer_type ras(ren);
|
||||
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 1)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras.add_path(path);
|
||||
}
|
||||
ras.add_path(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::wrap_mode_repeat wrap_x_type;
|
||||
typedef agg::wrap_mode_repeat wrap_y_type;
|
||||
typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
|
||||
agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
|
||||
typedef agg::image_accessor_wrap<rendering_buffer,
|
||||
typedef agg::image_accessor_wrap<rendering_buffer,
|
||||
wrap_x_type,
|
||||
wrap_y_type> img_source_type;
|
||||
|
||||
|
||||
typedef agg::span_pattern_rgba<img_source_type> span_gen_type;
|
||||
|
||||
typedef agg::renderer_scanline_aa<ren_base,
|
||||
|
||||
typedef agg::renderer_scanline_aa<ren_base,
|
||||
agg::span_allocator<agg::rgba8>,
|
||||
span_gen_type> renderer_type;
|
||||
|
||||
|
||||
span_gen_type> renderer_type;
|
||||
|
||||
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
ren_base renb(pixf);
|
||||
|
||||
|
||||
agg::scanline_u8 sl;
|
||||
ras_ptr->reset();
|
||||
|
||||
|
||||
ImageData32 const& pattern = * sym.get_image();
|
||||
unsigned w=pattern.width();
|
||||
unsigned h=pattern.height();
|
||||
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
|
||||
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
|
||||
agg::span_allocator<agg::rgba8> sa;
|
||||
agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
|
||||
agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
|
||||
img_source_type img_src(pixf_pattern);
|
||||
|
||||
|
||||
double x0=0,y0=0;
|
||||
unsigned num_geometries = feature.num_geometries();
|
||||
if (num_geometries>0)
|
||||
|
@ -645,18 +686,18 @@ namespace mapnik
|
|||
}
|
||||
unsigned offset_x = unsigned(width_-x0);
|
||||
unsigned offset_y = unsigned(height_-y0);
|
||||
span_gen_type sg(img_src, offset_x, offset_y);
|
||||
span_gen_type sg(img_src, offset_x, offset_y);
|
||||
renderer_type rp(renb,sa, sg);
|
||||
for (unsigned i=0;i<num_geometries;++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
}
|
||||
}
|
||||
agg::render_scanlines(*ras_ptr, sl, rp);
|
||||
agg::render_scanlines(*ras_ptr, sl, rp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -671,7 +712,7 @@ namespace mapnik
|
|||
ImageData32 target(int(ceil(ext.width())),int(ceil(ext.height())));
|
||||
int start_x = int(ext.minx()+0.5);
|
||||
int start_y = int(ext.miny()+0.5);
|
||||
|
||||
|
||||
if (sym.get_scaling() == "fast") {
|
||||
scale_image<ImageData32>(target,raster->data_);
|
||||
} else if (sym.get_scaling() == "bilinear"){
|
||||
|
@ -714,39 +755,39 @@ namespace mapnik
|
|||
// TODO: other modes? (add,diff,sub,...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
arrow arrow_;
|
||||
ras_ptr->reset();
|
||||
|
||||
|
||||
agg::scanline_u8 sl;
|
||||
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
|
||||
agg::pixfmt_rgba32_plain pixf(buf);
|
||||
ren_base renb(pixf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
|
||||
unsigned r = 0;// fill_.red();
|
||||
unsigned g = 0; //fill_.green();
|
||||
unsigned b = 255; //fill_.blue();
|
||||
unsigned a = 255; //fill_.alpha();
|
||||
renderer ren(renb);
|
||||
renderer ren(renb);
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom=feature.get_geometry(i);
|
||||
if (geom.num_points() > 1)
|
||||
if (geom.num_points() > 1)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
|
||||
agg::conv_dash <path_type> dash(path);
|
||||
dash.add_dash(20.0,200.0);
|
||||
markers_converter<agg::conv_dash<path_type>,
|
||||
arrow,
|
||||
markers_converter<agg::conv_dash<path_type>,
|
||||
arrow,
|
||||
label_collision_detector4>
|
||||
marker(dash, arrow_, detector_);
|
||||
ras_ptr->add_path(marker);
|
||||
|
@ -755,14 +796,14 @@ namespace mapnik
|
|||
ren.color(agg::rgba8(r, g, b, a));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
|
||||
|
||||
UnicodeString text = feature[sym.get_name()].to_unicode();
|
||||
if ( sym.get_text_convert() == TOUPPER)
|
||||
{
|
||||
|
@ -783,7 +824,7 @@ namespace mapnik
|
|||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
@ -795,35 +836,37 @@ namespace mapnik
|
|||
ren.set_fill(fill);
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius());
|
||||
|
||||
ren.set_opacity(sym.get_opacity());
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
|
||||
string_info info(text);
|
||||
|
||||
|
||||
faces->get_string_info(info);
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0;i<num_geom;++i)
|
||||
{
|
||||
geometry2d const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 0) // don't bother with empty geometries
|
||||
if (geom.num_points() > 0) // don't bother with empty geometries
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
placement text_placement(info,sym);
|
||||
placement text_placement(info,sym);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
{
|
||||
double label_x, label_y, z=0.0;
|
||||
geom.label_position(&label_x, &label_y);
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
finder.find_point_placement(text_placement,label_x,label_y,sym.get_vertical_alignment(),sym.get_line_spacing(),sym.get_character_spacing());
|
||||
finder.find_point_placement(text_placement,label_x,label_y,sym.get_vertical_alignment(),sym.get_line_spacing(),
|
||||
sym.get_character_spacing(),sym.get_horizontal_alignment(),sym.get_justify_alignment());
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
else if ( geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT)
|
||||
{
|
||||
finder.find_line_placements<path_type>(text_placement,path);
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
|
||||
{
|
||||
double x = text_placement.placements[ii].starting_x;
|
||||
|
@ -832,7 +875,7 @@ namespace mapnik
|
|||
ren.render(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
316
src/load_map.cpp
316
src/load_map.cpp
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -55,28 +55,28 @@ using boost::property_tree::ptree;
|
|||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
namespace mapnik
|
||||
namespace mapnik
|
||||
{
|
||||
using boost::optional;
|
||||
|
||||
class map_parser : boost::noncopyable {
|
||||
public:
|
||||
map_parser( bool strict, std::string const& filename = "" ) :
|
||||
map_parser( bool strict, std::string const& filename = "" ) :
|
||||
strict_( strict ),
|
||||
filename_( filename ),
|
||||
relative_to_xml_(true),
|
||||
font_manager_(font_engine_) {}
|
||||
|
||||
|
||||
void parse_map( Map & map, ptree const & sty);
|
||||
private:
|
||||
void parse_style( Map & map, ptree const & sty);
|
||||
void parse_layer( Map & map, ptree const & lay);
|
||||
|
||||
|
||||
void parse_fontset(Map & map, ptree const & fset);
|
||||
void parse_font(FontSet & fset, ptree const & f);
|
||||
|
||||
|
||||
void parse_rule( feature_type_style & style, ptree const & r);
|
||||
|
||||
|
||||
void parse_point_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_polygon_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
|
@ -87,11 +87,11 @@ namespace mapnik
|
|||
void parse_building_symbolizer( rule_type & rule, ptree const & sym );
|
||||
void parse_raster_symbolizer( rule_type & rule, ptree const & sym );
|
||||
void parse_markers_symbolizer( rule_type & rule, ptree const & sym );
|
||||
|
||||
|
||||
void ensure_font_face( const std::string & face_name );
|
||||
|
||||
|
||||
std::string ensure_relative_to_xml( boost::optional<std::string> opt_path );
|
||||
|
||||
|
||||
bool strict_;
|
||||
std::string filename_;
|
||||
bool relative_to_xml_;
|
||||
|
@ -127,7 +127,7 @@ namespace mapnik
|
|||
#ifdef HAVE_LIBXML2
|
||||
read_xml2_string(str, pt);
|
||||
#else
|
||||
try
|
||||
try
|
||||
{
|
||||
std::istringstream s(str);
|
||||
read_xml(s,pt);
|
||||
|
@ -218,7 +218,7 @@ namespace mapnik
|
|||
std::string name = get_attr<string>(param, "name");
|
||||
std::string value = get_own<string>( param,
|
||||
"datasource parameter");
|
||||
params[name] = value;
|
||||
params[name] = value;
|
||||
}
|
||||
else if( paramIter->first != "<xmlattr>" &&
|
||||
paramIter->first != "<xmlcomment>" )
|
||||
|
@ -255,7 +255,7 @@ namespace mapnik
|
|||
ptree::const_iterator ruleIter = sty.begin();
|
||||
ptree::const_iterator endRule = sty.end();
|
||||
|
||||
for (; ruleIter!=endRule; ++ruleIter)
|
||||
for (; ruleIter!=endRule; ++ruleIter)
|
||||
{
|
||||
ptree::value_type const& rule_tag = *ruleIter;
|
||||
if (rule_tag.first == "Rule")
|
||||
|
@ -291,7 +291,7 @@ namespace mapnik
|
|||
ptree::const_iterator itr = fset.begin();
|
||||
ptree::const_iterator end = fset.end();
|
||||
|
||||
for (; itr != end; ++itr)
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
ptree::value_type const& font_tag = *itr;
|
||||
|
||||
|
@ -308,8 +308,8 @@ namespace mapnik
|
|||
}
|
||||
|
||||
map.insert_fontset(name, fontset);
|
||||
|
||||
// XXX Hack because map object isn't accessible by text_symbolizer
|
||||
|
||||
// XXX Hack because map object isn't accessible by text_symbolizer
|
||||
// when it's parsed
|
||||
fontsets_.insert(pair<std::string, FontSet>(name, fontset));
|
||||
} catch (const config_error & ex) {
|
||||
|
@ -338,7 +338,7 @@ namespace mapnik
|
|||
try
|
||||
{
|
||||
name = get_attr(lay, "name", string("Unnamed"));
|
||||
|
||||
|
||||
// XXX if no projection is given inherit from map? [DS]
|
||||
std::string srs = get_attr(lay, "srs", map.srs());
|
||||
|
||||
|
@ -379,7 +379,7 @@ namespace mapnik
|
|||
{
|
||||
lyr.setQueryable( * queryable );
|
||||
}
|
||||
|
||||
|
||||
optional<boolean> clear_cache =
|
||||
get_opt_attr<boolean>(lay, "clear_label_cache");
|
||||
if (clear_cache)
|
||||
|
@ -409,8 +409,8 @@ namespace mapnik
|
|||
std::map<std::string,parameters>::const_iterator base_itr = datasource_templates_.find(*base);
|
||||
if (base_itr!=datasource_templates_.end())
|
||||
params = base_itr->second;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ptree::const_iterator paramIter = child.second.begin();
|
||||
ptree::const_iterator endParam = child.second.end();
|
||||
for (; paramIter != endParam; ++paramIter)
|
||||
|
@ -422,7 +422,7 @@ namespace mapnik
|
|||
std::string name = get_attr<string>(param, "name");
|
||||
std::string value = get_own<string>( param,
|
||||
"datasource parameter");
|
||||
params[name] = value;
|
||||
params[name] = value;
|
||||
}
|
||||
else if( paramIter->first != "<xmlattr>" &&
|
||||
paramIter->first != "<xmlcomment>" )
|
||||
|
@ -432,15 +432,15 @@ namespace mapnik
|
|||
paramIter->first + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( relative_to_xml_ ) {
|
||||
boost::optional<std::string> base_param = params.get<std::string>("base");
|
||||
boost::optional<std::string> file_param = params.get<std::string>("file");
|
||||
|
||||
|
||||
if (base_param){
|
||||
params["base"] = ensure_relative_to_xml(base_param);
|
||||
}
|
||||
|
||||
|
||||
else if (file_param){
|
||||
params["file"] = ensure_relative_to_xml(file_param);
|
||||
}
|
||||
|
@ -450,27 +450,27 @@ namespace mapnik
|
|||
std::clog << "\nFound relative paths in xml, leaving unchanged...\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
//now we are ready to create datasource
|
||||
try
|
||||
|
||||
//now we are ready to create datasource
|
||||
try
|
||||
{
|
||||
boost::shared_ptr<datasource> ds =
|
||||
datasource_cache::instance()->create(params);
|
||||
lyr.set_datasource(ds);
|
||||
}
|
||||
|
||||
|
||||
// catch problem at datasource registration
|
||||
catch (const mapnik::config_error & ex )
|
||||
{
|
||||
throw config_error( ex.what() );
|
||||
}
|
||||
|
||||
|
||||
// catch problem at the datasource creation
|
||||
catch (const mapnik::datasource_exception & ex )
|
||||
{
|
||||
throw config_error( ex.what() );
|
||||
}
|
||||
|
||||
|
||||
catch (...)
|
||||
{
|
||||
//throw config_error("exception...");
|
||||
|
@ -512,27 +512,27 @@ namespace mapnik
|
|||
// can we use encoding defined for XML document for filter expressions?
|
||||
rule.set_filter(create_filter(*filter_expr,"utf8"));
|
||||
}
|
||||
|
||||
optional<std::string> else_filter =
|
||||
|
||||
optional<std::string> else_filter =
|
||||
get_opt_child<string>(r, "ElseFilter");
|
||||
if (else_filter)
|
||||
{
|
||||
rule.set_else(true);
|
||||
}
|
||||
|
||||
optional<double> min_scale =
|
||||
optional<double> min_scale =
|
||||
get_opt_child<double>(r, "MinScaleDenominator");
|
||||
if (min_scale)
|
||||
{
|
||||
rule.set_min_scale(*min_scale);
|
||||
}
|
||||
|
||||
optional<double> max_scale =
|
||||
optional<double> max_scale =
|
||||
get_opt_child<double>(r, "MaxScaleDenominator");
|
||||
if (max_scale)
|
||||
if (max_scale)
|
||||
{
|
||||
rule.set_max_scale(*max_scale);
|
||||
}
|
||||
rule.set_max_scale(*max_scale);
|
||||
}
|
||||
|
||||
ptree::const_iterator symIter = r.begin();
|
||||
ptree::const_iterator endSym = r.end();
|
||||
|
@ -544,7 +544,7 @@ namespace mapnik
|
|||
if ( sym.first == "PointSymbolizer")
|
||||
{
|
||||
parse_point_symbolizer( rule, sym.second );
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "LinePatternSymbolizer")
|
||||
{
|
||||
parse_line_pattern_symbolizer( rule, sym.second );
|
||||
|
@ -564,24 +564,24 @@ namespace mapnik
|
|||
else if ( sym.first == "LineSymbolizer")
|
||||
{
|
||||
parse_line_symbolizer( rule, sym.second );
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "PolygonSymbolizer")
|
||||
{
|
||||
parse_polygon_symbolizer( rule, sym.second );
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "BuildingSymbolizer")
|
||||
{
|
||||
parse_building_symbolizer( rule, sym.second );
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "RasterSymbolizer")
|
||||
{
|
||||
parse_raster_symbolizer( rule, sym.second );
|
||||
}
|
||||
}
|
||||
else if ( sym.first == "MarkersSymbolizer")
|
||||
{
|
||||
rule.append(markers_symbolizer());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if ( sym.first != "MinScaleDenominator" &&
|
||||
sym.first != "MaxScaleDenominator" &&
|
||||
sym.first != "Filter" &&
|
||||
|
@ -592,7 +592,7 @@ namespace mapnik
|
|||
throw config_error(std::string("Unknown symbolizer '") +
|
||||
sym.first + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style.add_rule(rule);
|
||||
|
||||
|
@ -609,18 +609,18 @@ namespace mapnik
|
|||
|
||||
void map_parser::parse_point_symbolizer( rule_type & rule, ptree const & sym )
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
optional<std::string> file = get_opt_attr<string>(sym, "file");
|
||||
optional<std::string> base = get_opt_attr<string>(sym, "base");
|
||||
optional<std::string> type = get_opt_attr<string>(sym, "type");
|
||||
optional<boolean> allow_overlap =
|
||||
optional<std::string> type = get_opt_attr<string>(sym, "type");
|
||||
optional<boolean> allow_overlap =
|
||||
get_opt_attr<boolean>(sym, "allow_overlap");
|
||||
optional<float> opacity =
|
||||
optional<float> opacity =
|
||||
get_opt_attr<float>(sym, "opacity");
|
||||
|
||||
optional<unsigned> width = get_opt_attr<unsigned>(sym, "width");
|
||||
optional<unsigned> height = get_opt_attr<unsigned>(sym, "height");
|
||||
optional<unsigned> width = get_opt_attr<unsigned>(sym, "width");
|
||||
optional<unsigned> height = get_opt_attr<unsigned>(sym, "height");
|
||||
|
||||
if (file && type && width && height)
|
||||
{
|
||||
|
@ -634,9 +634,9 @@ namespace mapnik
|
|||
*file = itr->second + "/" + *file;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( relative_to_xml_ )
|
||||
{
|
||||
{
|
||||
*file = ensure_relative_to_xml(file);
|
||||
}
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
@ -644,7 +644,7 @@ namespace mapnik
|
|||
std::clog << "\nFound relative paths in xml, leaving unchanged...\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
point_symbolizer symbol(*file,*type,*width,*height);
|
||||
if (allow_overlap)
|
||||
{
|
||||
|
@ -653,7 +653,7 @@ namespace mapnik
|
|||
if (opacity)
|
||||
{
|
||||
symbol.set_opacity( * opacity );
|
||||
}
|
||||
}
|
||||
rule.append(symbol);
|
||||
}
|
||||
catch (ImageReaderException const & ex )
|
||||
|
@ -681,12 +681,12 @@ namespace mapnik
|
|||
if ( ! height ) os << "height ";
|
||||
throw config_error( os.str() );
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
rule.append(point_symbolizer());
|
||||
}
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PointSymbolizer");
|
||||
throw;
|
||||
|
@ -695,11 +695,11 @@ namespace mapnik
|
|||
|
||||
void map_parser::parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym )
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
std::string file = get_attr<string>(sym, "file");
|
||||
optional<std::string> base = get_opt_attr<string>(sym, "base");
|
||||
std::string type = get_attr<string>(sym, "type");
|
||||
std::string type = get_attr<string>(sym, "type");
|
||||
unsigned width = get_attr<unsigned>(sym, "width");
|
||||
unsigned height = get_attr<unsigned>(sym, "height");
|
||||
|
||||
|
@ -714,7 +714,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
if ( relative_to_xml_ )
|
||||
{
|
||||
{
|
||||
file = ensure_relative_to_xml(file);
|
||||
}
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
@ -722,7 +722,7 @@ namespace mapnik
|
|||
std::clog << "\nFound relative paths in xml, leaving unchanged...\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
line_pattern_symbolizer symbol(file,type,width,height);
|
||||
rule.append(symbol);
|
||||
|
@ -741,7 +741,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in LinePatternSymbolizer");
|
||||
throw;
|
||||
|
@ -751,11 +751,11 @@ namespace mapnik
|
|||
void map_parser::parse_polygon_pattern_symbolizer( rule_type & rule,
|
||||
ptree const & sym )
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
std::string file = get_attr<string>(sym, "file");
|
||||
optional<std::string> base = get_opt_attr<string>(sym, "base");
|
||||
std::string type = get_attr<string>(sym, "type");
|
||||
std::string type = get_attr<string>(sym, "type");
|
||||
unsigned width = get_attr<unsigned>(sym, "width");
|
||||
unsigned height = get_attr<unsigned>(sym, "height");
|
||||
|
||||
|
@ -770,7 +770,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
if ( relative_to_xml_ )
|
||||
{
|
||||
{
|
||||
file = ensure_relative_to_xml(file);
|
||||
}
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
@ -796,7 +796,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PolygonPatternSymbolizer");
|
||||
throw;
|
||||
|
@ -807,20 +807,20 @@ namespace mapnik
|
|||
{
|
||||
try
|
||||
{
|
||||
std::string name = get_attr<string>(sym, "name");
|
||||
std::string name = get_attr<string>(sym, "name");
|
||||
|
||||
optional<std::string> face_name =
|
||||
get_opt_attr<std::string>(sym, "face_name");
|
||||
|
||||
|
||||
optional<std::string> fontset_name =
|
||||
get_opt_attr<std::string>(sym, "fontset_name");
|
||||
|
||||
unsigned size = get_attr(sym, "size", 10U);
|
||||
|
||||
color c = get_attr(sym, "fill", color(0,0,0));
|
||||
|
||||
text_symbolizer text_symbol = text_symbolizer(name, size, c);
|
||||
|
||||
|
||||
text_symbolizer text_symbol = text_symbolizer(name, size, c);
|
||||
|
||||
if (fontset_name && face_name)
|
||||
{
|
||||
throw config_error(std::string("Can't have both face_name and fontset_name"));
|
||||
|
@ -830,7 +830,7 @@ namespace mapnik
|
|||
std::map<std::string,FontSet>::const_iterator itr = fontsets_.find(*fontset_name);
|
||||
if (itr != fontsets_.end())
|
||||
{
|
||||
text_symbol.set_fontset(itr->second);
|
||||
text_symbol.set_fontset(itr->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -857,17 +857,17 @@ namespace mapnik
|
|||
label_placement_e placement =
|
||||
get_attr<label_placement_e>(sym, "placement", POINT_PLACEMENT);
|
||||
text_symbol.set_label_placement( placement );
|
||||
// vertical alignment
|
||||
// vertical alignment
|
||||
vertical_alignment_e valign = get_attr<vertical_alignment_e>(sym, "vertical_alignment", BOTTOM);
|
||||
text_symbol.set_vertical_alignment(valign);
|
||||
|
||||
text_symbol.set_vertical_alignment(valign);
|
||||
// halo fill and radius
|
||||
optional<color> halo_fill = get_opt_attr<color>(sym, "halo_fill");
|
||||
if (halo_fill)
|
||||
{
|
||||
text_symbol.set_halo_fill( * halo_fill );
|
||||
}
|
||||
optional<unsigned> halo_radius =
|
||||
optional<unsigned> halo_radius =
|
||||
get_opt_attr<unsigned>(sym, "halo_radius");
|
||||
if (halo_radius)
|
||||
{
|
||||
|
@ -875,18 +875,29 @@ namespace mapnik
|
|||
}
|
||||
|
||||
// text ratio and wrap width
|
||||
optional<unsigned> text_ratio =
|
||||
optional<unsigned> text_ratio =
|
||||
get_opt_attr<unsigned>(sym, "text_ratio");
|
||||
if (text_ratio)
|
||||
{
|
||||
text_symbol.set_text_ratio(*text_ratio);
|
||||
}
|
||||
|
||||
optional<unsigned> wrap_width =
|
||||
optional<unsigned> wrap_width =
|
||||
get_opt_attr<unsigned>(sym, "wrap_width");
|
||||
if (wrap_width)
|
||||
{
|
||||
text_symbol.set_wrap_width(*wrap_width);
|
||||
}
|
||||
|
||||
optional<boolean> wrap_before =
|
||||
get_opt_attr<boolean>(sym, "wrap_before");
|
||||
if (wrap_before)
|
||||
{
|
||||
text_symbol.set_wrap_before(*wrap_before);
|
||||
}
|
||||
|
||||
// character used to break long strings
|
||||
optional<std::string> wrap_char =
|
||||
optional<std::string> wrap_char =
|
||||
get_opt_attr<std::string>(sym, "wrap_character");
|
||||
if (wrap_char && (*wrap_char).size() > 0)
|
||||
{
|
||||
|
@ -935,25 +946,41 @@ namespace mapnik
|
|||
text_symbol.set_avoid_edges( * avoid_edges);
|
||||
}
|
||||
|
||||
// allow_overlap
|
||||
optional<boolean> allow_overlap =
|
||||
// allow_overlap
|
||||
optional<boolean> allow_overlap =
|
||||
get_opt_attr<boolean>(sym, "allow_overlap");
|
||||
if (allow_overlap)
|
||||
{
|
||||
text_symbol.set_allow_overlap( * allow_overlap );
|
||||
}
|
||||
|
||||
|
||||
// opacity
|
||||
optional<double> opacity =
|
||||
get_opt_attr<double>(sym, "opacity");
|
||||
if (opacity)
|
||||
{
|
||||
text_symbol.set_opacity( * opacity );
|
||||
}
|
||||
|
||||
// max_char_angle_delta
|
||||
optional<double> max_char_angle_delta =
|
||||
optional<double> max_char_angle_delta =
|
||||
get_opt_attr<double>(sym, "max_char_angle_delta");
|
||||
if (max_char_angle_delta)
|
||||
{
|
||||
text_symbol.set_max_char_angle_delta( * max_char_angle_delta);
|
||||
}
|
||||
|
||||
|
||||
// horizontal alignment
|
||||
horizontal_alignment_e halign = get_attr<horizontal_alignment_e>(sym, "horizontal_alignment", H_MIDDLE);
|
||||
text_symbol.set_horizontal_alignment(halign);
|
||||
|
||||
// justify alignment
|
||||
justify_alignment_e jalign = get_attr<justify_alignment_e>(sym, "justify_alignment", J_MIDDLE);
|
||||
text_symbol.set_justify_alignment(jalign);
|
||||
|
||||
rule.append(text_symbol);
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in TextSymbolizer");
|
||||
throw;
|
||||
|
@ -991,9 +1018,9 @@ namespace mapnik
|
|||
image_file = itr->second + "/" + image_file;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( relative_to_xml_ )
|
||||
{
|
||||
{
|
||||
image_file = ensure_relative_to_xml(image_file);
|
||||
}
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
@ -1001,7 +1028,7 @@ namespace mapnik
|
|||
std::clog << "\nFound relative paths in xml, leaving unchanged...\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
shield_symbolizer shield_symbol(name,size,fill,
|
||||
image_file,type,width,height);
|
||||
|
||||
|
@ -1014,7 +1041,7 @@ namespace mapnik
|
|||
std::map<std::string,FontSet>::const_iterator itr = fontsets_.find(*fontset_name);
|
||||
if (itr != fontsets_.end())
|
||||
{
|
||||
shield_symbol.set_fontset(itr->second);
|
||||
shield_symbol.set_fontset(itr->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1037,7 +1064,7 @@ namespace mapnik
|
|||
double dx = get_attr(sym, "dx", 0.0);
|
||||
double dy = get_attr(sym, "dy", 0.0);
|
||||
shield_symbol.set_displacement(dx,dy);
|
||||
|
||||
|
||||
label_placement_e placement =
|
||||
get_attr<label_placement_e>(sym, "placement", POINT_PLACEMENT);
|
||||
shield_symbol.set_label_placement( placement );
|
||||
|
@ -1049,35 +1076,120 @@ namespace mapnik
|
|||
{
|
||||
shield_symbol.set_avoid_edges( *avoid_edges);
|
||||
}
|
||||
|
||||
|
||||
// halo fill and radius
|
||||
optional<color> halo_fill = get_opt_attr<color>(sym, "halo_fill");
|
||||
if (halo_fill)
|
||||
{
|
||||
shield_symbol.set_halo_fill( * halo_fill );
|
||||
}
|
||||
optional<unsigned> halo_radius =
|
||||
optional<unsigned> halo_radius =
|
||||
get_opt_attr<unsigned>(sym, "halo_radius");
|
||||
if (halo_radius)
|
||||
{
|
||||
shield_symbol.set_halo_radius(*halo_radius);
|
||||
}
|
||||
|
||||
|
||||
// minimum distance between labels
|
||||
optional<unsigned> min_distance =
|
||||
optional<unsigned> min_distance =
|
||||
get_opt_attr<unsigned>(sym, "min_distance");
|
||||
if (min_distance)
|
||||
{
|
||||
shield_symbol.set_minimum_distance(*min_distance);
|
||||
}
|
||||
|
||||
|
||||
// spacing between repeated labels on lines
|
||||
optional<unsigned> spacing = get_opt_attr<unsigned>(sym, "spacing");
|
||||
if (spacing)
|
||||
{
|
||||
shield_symbol.set_label_spacing(*spacing);
|
||||
}
|
||||
|
||||
|
||||
// allow_overlap
|
||||
optional<boolean> allow_overlap =
|
||||
get_opt_attr<boolean>(sym, "allow_overlap");
|
||||
if (allow_overlap)
|
||||
{
|
||||
shield_symbol.set_allow_overlap( * allow_overlap );
|
||||
}
|
||||
|
||||
// vertical alignment
|
||||
vertical_alignment_e valign = get_attr<vertical_alignment_e>(sym, "vertical_alignment", BOTTOM);
|
||||
shield_symbol.set_vertical_alignment(valign);
|
||||
|
||||
// horizontal alignment
|
||||
horizontal_alignment_e halign = get_attr<horizontal_alignment_e>(sym, "horizontal_alignment", H_MIDDLE);
|
||||
shield_symbol.set_horizontal_alignment(halign);
|
||||
|
||||
// justify alignment
|
||||
justify_alignment_e jalign = get_attr<justify_alignment_e>(sym, "justify_alignment", J_MIDDLE);
|
||||
shield_symbol.set_justify_alignment(jalign);
|
||||
|
||||
optional<unsigned> wrap_width =
|
||||
get_opt_attr<unsigned>(sym, "wrap_width");
|
||||
if (wrap_width)
|
||||
{
|
||||
shield_symbol.set_wrap_width(*wrap_width);
|
||||
}
|
||||
|
||||
optional<boolean> wrap_before =
|
||||
get_opt_attr<boolean>(sym, "wrap_before");
|
||||
if (wrap_before)
|
||||
{
|
||||
shield_symbol.set_wrap_before(*wrap_before);
|
||||
}
|
||||
|
||||
// character used to break long strings
|
||||
optional<std::string> wrap_char =
|
||||
get_opt_attr<std::string>(sym, "wrap_character");
|
||||
if (wrap_char && (*wrap_char).size() > 0)
|
||||
{
|
||||
shield_symbol.set_wrap_char((*wrap_char)[0]);
|
||||
}
|
||||
|
||||
// text conversion before rendering
|
||||
text_convert_e tconvert =
|
||||
get_attr<text_convert_e>(sym, "text_convert", NONE);
|
||||
shield_symbol.set_text_convert(tconvert);
|
||||
|
||||
// spacing between text lines
|
||||
optional<unsigned> line_spacing = get_opt_attr<unsigned>(sym, "line_spacing");
|
||||
if (line_spacing)
|
||||
{
|
||||
shield_symbol.set_line_spacing(*line_spacing);
|
||||
}
|
||||
|
||||
// spacing between characters in text
|
||||
optional<unsigned> character_spacing = get_opt_attr<unsigned>(sym, "character_spacing");
|
||||
if (character_spacing)
|
||||
{
|
||||
shield_symbol.set_character_spacing(*character_spacing);
|
||||
}
|
||||
|
||||
// opacity
|
||||
optional<double> opacity =
|
||||
get_opt_attr<double>(sym, "opacity");
|
||||
if (opacity)
|
||||
{
|
||||
shield_symbol.set_opacity( * opacity );
|
||||
}
|
||||
|
||||
// unlock_image
|
||||
optional<boolean> unlock_image =
|
||||
get_opt_attr<boolean>(sym, "unlock_image");
|
||||
if (unlock_image)
|
||||
{
|
||||
shield_symbol.set_unlock_image( * unlock_image );
|
||||
}
|
||||
|
||||
// no text
|
||||
optional<boolean> no_text =
|
||||
get_opt_attr<boolean>(sym, "no_text");
|
||||
if (no_text)
|
||||
{
|
||||
shield_symbol.set_no_text( * no_text );
|
||||
}
|
||||
|
||||
rule.append(shield_symbol);
|
||||
}
|
||||
catch (ImageReaderException const & ex )
|
||||
|
@ -1093,9 +1205,9 @@ namespace mapnik
|
|||
clog << "### WARNING: " << msg << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in ShieldSymbolizer");
|
||||
throw;
|
||||
|
@ -1195,7 +1307,7 @@ namespace mapnik
|
|||
}
|
||||
rule.append(line_symbolizer(strk));
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in LineSymbolizer");
|
||||
throw;
|
||||
|
@ -1246,7 +1358,7 @@ namespace mapnik
|
|||
rule.append(poly_sym);
|
||||
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PolygonSymbolizer");
|
||||
throw;
|
||||
|
@ -1301,12 +1413,12 @@ namespace mapnik
|
|||
}
|
||||
rule.append(building_sym);
|
||||
}
|
||||
catch (const config_error & ex)
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in BuildingSymbolizer");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_parser::parse_raster_symbolizer( rule_type & rule, ptree const & sym )
|
||||
{
|
||||
|
@ -1368,7 +1480,7 @@ namespace mapnik
|
|||
face_name + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string map_parser::ensure_relative_to_xml( boost::optional<std::string> opt_path )
|
||||
{
|
||||
boost::filesystem::path xml_path = filename_;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -49,49 +49,54 @@
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
placement::placement(string_info & info_,
|
||||
placement::placement(string_info & info_,
|
||||
shield_symbolizer const& sym, bool has_dimensions_)
|
||||
: info(info_),
|
||||
: info(info_),
|
||||
displacement_(sym.get_displacement()),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
text_ratio(sym.get_text_ratio()),
|
||||
label_spacing(sym.get_label_spacing()),
|
||||
label_position_tolerance(sym.get_label_position_tolerance()),
|
||||
force_odd_labels(sym.get_force_odd_labels()),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
wrap_before(sym.get_wrap_before()),
|
||||
wrap_char(sym.get_wrap_char()),
|
||||
text_ratio(sym.get_text_ratio()),
|
||||
label_spacing(sym.get_label_spacing()),
|
||||
label_position_tolerance(sym.get_label_position_tolerance()),
|
||||
force_odd_labels(sym.get_force_odd_labels()),
|
||||
max_char_angle_delta(sym.get_max_char_angle_delta()),
|
||||
minimum_distance(sym.get_minimum_distance()),
|
||||
avoid_edges(sym.get_avoid_edges()),
|
||||
has_dimensions(has_dimensions_),
|
||||
has_dimensions(has_dimensions_),
|
||||
allow_overlap(false),
|
||||
dimensions(std::make_pair(sym.get_image()->width(),
|
||||
sym.get_image()->height()))
|
||||
sym.get_image()->height())),
|
||||
text_size(sym.get_text_size())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
placement::placement(string_info & info_,
|
||||
text_symbolizer const& sym)
|
||||
: info(info_),
|
||||
: info(info_),
|
||||
displacement_(sym.get_displacement()),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
wrap_before(sym.get_wrap_before()),
|
||||
wrap_char(sym.get_wrap_char()),
|
||||
text_ratio(sym.get_text_ratio()),
|
||||
label_spacing(sym.get_label_spacing()),
|
||||
label_position_tolerance(sym.get_label_position_tolerance()),
|
||||
force_odd_labels(sym.get_force_odd_labels()),
|
||||
text_ratio(sym.get_text_ratio()),
|
||||
label_spacing(sym.get_label_spacing()),
|
||||
label_position_tolerance(sym.get_label_position_tolerance()),
|
||||
force_odd_labels(sym.get_force_odd_labels()),
|
||||
max_char_angle_delta(sym.get_max_char_angle_delta()),
|
||||
minimum_distance(sym.get_minimum_distance()),
|
||||
avoid_edges(sym.get_avoid_edges()),
|
||||
has_dimensions(false),
|
||||
allow_overlap(sym.get_allow_overlap()),
|
||||
dimensions()
|
||||
dimensions(),
|
||||
text_size(sym.get_text_size())
|
||||
{
|
||||
}
|
||||
placement::~placement()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::pair<double, double> get_position_at_distance(double target_distance, T & shape_path)
|
||||
{
|
||||
|
@ -115,10 +120,10 @@ namespace mapnik
|
|||
{
|
||||
double dx = x2-x1;
|
||||
double dy = y2-y1;
|
||||
|
||||
|
||||
double segment_length = std::sqrt(dx*dx + dy*dy);
|
||||
distance +=segment_length;
|
||||
|
||||
|
||||
if (distance > target_distance)
|
||||
{
|
||||
x = x2 - dx * (distance - target_distance)/segment_length;
|
||||
|
@ -131,13 +136,13 @@ namespace mapnik
|
|||
}
|
||||
return std::pair<double, double>(x, y);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
double get_total_distance(T & shape_path)
|
||||
{
|
||||
return agg::path_length(shape_path);
|
||||
}
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
placement_finder<DetectorT>::placement_finder(DetectorT & detector)
|
||||
: detector_(detector),
|
||||
|
@ -158,7 +163,7 @@ namespace mapnik
|
|||
|
||||
double total_distance = get_total_distance<T>(shape_path);
|
||||
shape_path.rewind(0);
|
||||
|
||||
|
||||
if (distance == 0) //Point data, not a line
|
||||
{
|
||||
double x, y;
|
||||
|
@ -166,20 +171,20 @@ namespace mapnik
|
|||
find_point_placement(p, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int num_labels = 1;
|
||||
if (p.label_spacing > 0)
|
||||
num_labels = static_cast<int> (floor(total_distance / p.label_spacing));
|
||||
|
||||
|
||||
if (p.force_odd_labels && num_labels%2 == 0)
|
||||
num_labels--;
|
||||
if (num_labels <= 0)
|
||||
num_labels = 1;
|
||||
|
||||
|
||||
double distance = 0.0; // distance from last label
|
||||
double spacing = total_distance / num_labels;
|
||||
double target_distance = spacing / 2; // first label should be placed at half the spacing
|
||||
|
||||
|
||||
while (!agg::is_stop(cmd = shape_path.vertex(&new_x,&new_y))) //For each node in the shape
|
||||
{
|
||||
|
||||
|
@ -187,201 +192,230 @@ namespace mapnik
|
|||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
//Add the length of this segment to the total we have saved up
|
||||
double segment_length = std::sqrt(std::pow(old_x-new_x,2) + std::pow(old_y-new_y,2)); //Pythagoras
|
||||
distance += segment_length;
|
||||
|
||||
|
||||
//While we have enough distance to place text in
|
||||
while (distance > target_distance)
|
||||
{
|
||||
//Try place at the specified place
|
||||
double new_weight = (segment_length - (distance - target_distance))/segment_length;
|
||||
find_point_placement(p, old_x + (new_x-old_x)*new_weight, old_y + (new_y-old_y)*new_weight);
|
||||
|
||||
|
||||
distance -= target_distance; //Consume the spacing gap we have used up
|
||||
target_distance = spacing; //Need to reset the target_distance as it is spacing/2 for the first label.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
void placement_finder<DetectorT>::find_point_placement(placement & p,
|
||||
double label_x,
|
||||
void placement_finder<DetectorT>::find_point_placement(placement & p,
|
||||
double label_x,
|
||||
double label_y,
|
||||
vertical_alignment_e valign,
|
||||
unsigned line_spacing,
|
||||
unsigned character_spacing)
|
||||
unsigned character_spacing,
|
||||
horizontal_alignment_e halign,
|
||||
justify_alignment_e jalign)
|
||||
{
|
||||
double x, y;
|
||||
std::auto_ptr<placement_element> current_placement(new placement_element);
|
||||
|
||||
|
||||
std::pair<double, double> string_dimensions = p.info.get_dimensions();
|
||||
double string_width = string_dimensions.first;
|
||||
double string_width = string_dimensions.first + (character_spacing *(p.info.num_characters()-1));
|
||||
double string_height = string_dimensions.second;
|
||||
|
||||
|
||||
// use height of tallest character in the string for the 'line' spacing to obtain consistent line spacing
|
||||
double max_character_height = string_height; // height of the tallest character in the string
|
||||
|
||||
// check if we need to wrap the string
|
||||
double wrap_at = string_width + 1;
|
||||
double wrap_at = string_width + 1.0;
|
||||
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);
|
||||
for (double i = 1.0; ((wrap_at = string_width/i)/(string_height*i)) > p.text_ratio && (string_width/i) > p.wrap_width; i += 1.0);
|
||||
else
|
||||
wrap_at = p.wrap_width;
|
||||
}
|
||||
|
||||
// work out where our line breaks need to be
|
||||
|
||||
// work out where our line breaks need to be and the resultant width to the 'wrapped' string
|
||||
std::vector<int> line_breaks;
|
||||
std::vector<double> line_widths;
|
||||
std::vector<double> line_heights;
|
||||
|
||||
if (wrap_at < string_width && p.info.num_characters() > 0)
|
||||
{
|
||||
int last_wrap_char = 0;
|
||||
string_width = 0;
|
||||
string_height = 0;
|
||||
double line_width = 0;
|
||||
double line_height = 0;
|
||||
double word_width = 0;
|
||||
double word_height = 0;
|
||||
int last_wrap_char_width = 0;
|
||||
string_width = 0.0;
|
||||
string_height = 0.0;
|
||||
double line_width = 0.0;
|
||||
double word_width = 0.0;
|
||||
|
||||
for (unsigned int ii = 0; ii < p.info.num_characters(); ii++)
|
||||
{
|
||||
character_info ci;
|
||||
ci = p.info.at(ii);
|
||||
|
||||
unsigned cwidth = ci.width + character_spacing;
|
||||
|
||||
double cwidth = ci.width + character_spacing;
|
||||
|
||||
unsigned c = ci.character;
|
||||
word_width += cwidth;
|
||||
word_height = word_height > (ci.height + line_spacing) ? word_height : (ci.height + line_spacing);
|
||||
|
||||
|
||||
if (c == p.wrap_char)
|
||||
{
|
||||
last_wrap_char = ii;
|
||||
last_wrap_char_width = cwidth;
|
||||
line_width += word_width;
|
||||
line_height = line_height > word_height ? line_height : word_height;
|
||||
word_width = 0;
|
||||
word_height = 0;
|
||||
word_width = 0.0;
|
||||
}
|
||||
if (line_width > 0 && line_width > wrap_at)
|
||||
|
||||
// wrap text at first wrap_char after (default) the wrap width or immediately before the current word
|
||||
if (line_width > 0 && (((line_width - character_spacing) > wrap_at && !p.wrap_before) ||
|
||||
((line_width + word_width - character_spacing) > wrap_at && p.wrap_before)) )
|
||||
{
|
||||
// Remove width of breaking space character since it is not rendered
|
||||
line_width -= cwidth;
|
||||
// Remove width of breaking space character since it is not rendered and the character_spacing for the last character on the line
|
||||
line_width -= (last_wrap_char_width + character_spacing);
|
||||
string_width = string_width > line_width ? string_width : line_width;
|
||||
string_height += line_height;
|
||||
string_height += max_character_height;
|
||||
line_breaks.push_back(last_wrap_char);
|
||||
line_widths.push_back(line_width);
|
||||
line_heights.push_back(line_height);
|
||||
ii = last_wrap_char;
|
||||
line_width = 0;
|
||||
line_height = 0;
|
||||
word_width = 0;
|
||||
word_height = 0;
|
||||
line_width = 0.0;
|
||||
word_width = 0.0;
|
||||
}
|
||||
}
|
||||
line_width += word_width;
|
||||
line_height = line_height > word_height ? line_height : word_height;
|
||||
line_width += (word_width - character_spacing); // remove character_spacing from last character on the line
|
||||
string_width = string_width > line_width ? string_width : line_width;
|
||||
string_height += line_height;
|
||||
line_breaks.push_back(p.info.num_characters() + 1);
|
||||
string_height += max_character_height;
|
||||
line_breaks.push_back(p.info.num_characters());
|
||||
line_widths.push_back(line_width);
|
||||
line_heights.push_back(line_height);
|
||||
}
|
||||
if (line_breaks.size() == 0)
|
||||
{
|
||||
line_breaks.push_back(p.info.num_characters() + 1);
|
||||
line_breaks.push_back(p.info.num_characters());
|
||||
line_widths.push_back(string_width);
|
||||
line_heights.push_back(string_height);
|
||||
}
|
||||
|
||||
p.info.set_dimensions(string_width, string_height);
|
||||
|
||||
unsigned int line_number = 0;
|
||||
unsigned int index_to_wrap_at = line_breaks[line_number];
|
||||
double line_width = line_widths[line_number];
|
||||
double line_height = line_heights[line_number];
|
||||
|
||||
current_placement->starting_x = label_x;
|
||||
if (valign == BOTTOM)
|
||||
{
|
||||
current_placement->starting_y = label_y;
|
||||
}
|
||||
else if (valign == MIDDLE)
|
||||
{
|
||||
current_placement->starting_y = label_y - 0.5 * (line_heights.size() - 1) * line_height ;
|
||||
}
|
||||
else // TOP
|
||||
{
|
||||
current_placement->starting_y = label_y - line_heights.size() * line_height;
|
||||
}
|
||||
|
||||
current_placement->starting_x += boost::tuples::get<0>(p.displacement_);
|
||||
current_placement->starting_y += boost::tuples::get<1>(p.displacement_);
|
||||
int total_lines = line_breaks.size();
|
||||
|
||||
x = -line_width/2.0;
|
||||
y = -line_height/2.0;
|
||||
|
||||
p.info.set_dimensions( string_width, (string_height + (line_spacing * (total_lines-1))) );
|
||||
|
||||
// if needed, adjust for desired vertical alignment
|
||||
current_placement->starting_y = label_y; // no adjustment, default is MIDDLE
|
||||
|
||||
if (valign == 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)
|
||||
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 )
|
||||
current_placement->starting_y -= (p.text_size - max_character_height); // move up by the error
|
||||
|
||||
else if (valign == 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)
|
||||
current_placement->starting_x -= 0.5 * string_width; // move center left by 1/2 the string width
|
||||
|
||||
else if (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)
|
||||
current_placement->starting_x += boost::tuples::get<0>(p.displacement_);
|
||||
current_placement->starting_y += boost::tuples::get<1>(p.displacement_);
|
||||
|
||||
// presets for first line
|
||||
unsigned int line_number = 0;
|
||||
unsigned int index_to_wrap_at = line_breaks[0];
|
||||
double line_width = line_widths[0];
|
||||
|
||||
// set for upper left corner of text envelope for the first line, bottom left of first character
|
||||
x = -(line_width / 2.0);
|
||||
y = (0.5 * (string_height + (line_spacing * (total_lines-1)))) - max_character_height;
|
||||
|
||||
// if needed, adjust for desired justification (J_MIDDLE is the default)
|
||||
if( jalign == J_LEFT )
|
||||
x = -(string_width / 2.0);
|
||||
|
||||
else if (jalign == J_RIGHT)
|
||||
x = (string_width / 2.0) - line_width;
|
||||
|
||||
// save each character rendering position and build envelope as go thru loop
|
||||
for (unsigned i = 0; i < p.info.num_characters(); i++)
|
||||
{
|
||||
character_info ci;
|
||||
ci = p.info.at(i);
|
||||
|
||||
unsigned cwidth = ci.width + character_spacing;
|
||||
|
||||
double cwidth = ci.width + character_spacing;
|
||||
|
||||
unsigned c = ci.character;
|
||||
if (i == index_to_wrap_at)
|
||||
{
|
||||
index_to_wrap_at = line_breaks[++line_number];
|
||||
line_width = line_widths[line_number];
|
||||
line_height = line_heights[line_number];
|
||||
y -= line_height;
|
||||
x = -line_width/2.0;
|
||||
|
||||
y -= (max_character_height + line_spacing); // move position down to line start
|
||||
|
||||
// reset to begining of line position
|
||||
x = ((jalign == J_LEFT)? -(string_width / 2.0): ((jalign == J_RIGHT)? ((string_width /2.0) - line_width): -(line_width / 2.0)));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// place the character relative to the center of the string envelope
|
||||
current_placement->add_node(c, x, y, 0.0);
|
||||
|
||||
|
||||
// compute the Bounding Box for each character and test for:
|
||||
// overlap, minimum distance or edge avoidance - exit if condition occurs
|
||||
Envelope<double> e;
|
||||
if (p.has_dimensions)
|
||||
{
|
||||
e.init(current_placement->starting_x - (p.dimensions.first/2.0),
|
||||
current_placement->starting_y - (p.dimensions.second/2.0),
|
||||
current_placement->starting_x + (p.dimensions.first/2.0),
|
||||
e.init(current_placement->starting_x - (p.dimensions.first/2.0), // Top Left
|
||||
current_placement->starting_y - (p.dimensions.second/2.0),
|
||||
|
||||
current_placement->starting_x + (p.dimensions.first/2.0), // Bottom Right
|
||||
current_placement->starting_y + (p.dimensions.second/2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
e.init(current_placement->starting_x + x,
|
||||
current_placement->starting_y - y,
|
||||
current_placement->starting_x + x + ci.width,
|
||||
current_placement->starting_y - y - ci.height);
|
||||
e.init(current_placement->starting_x + x, // Bottom Left
|
||||
current_placement->starting_y - y,
|
||||
|
||||
current_placement->starting_x + x + ci.width, // Top Right
|
||||
current_placement->starting_y - y - max_character_height);
|
||||
}
|
||||
|
||||
if (!dimensions_.intersects(e) ||
|
||||
(!p.allow_overlap && !detector_.has_point_placement(e,
|
||||
p.minimum_distance)))
|
||||
|
||||
if (!dimensions_.intersects(e) ||
|
||||
(!p.allow_overlap && !detector_.has_point_placement(e,p.minimum_distance)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (p.avoid_edges && !dimensions_.contains(e)) return;
|
||||
|
||||
|
||||
p.envelopes.push(e);
|
||||
}
|
||||
x += cwidth;
|
||||
x += cwidth; // move position to next character
|
||||
}
|
||||
p.placements.push_back(current_placement.release());
|
||||
//update_detector(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
template <typename PathT>
|
||||
void placement_finder<DetectorT>::find_line_placements(placement & p, PathT & shape_path)
|
||||
|
@ -392,14 +426,14 @@ p.minimum_distance)))
|
|||
double old_x = 0.0;
|
||||
double old_y = 0.0;
|
||||
bool first = true;
|
||||
|
||||
|
||||
//Pre-Cache all the path_positions and path_distances
|
||||
//This stops the PathT from having to do multiple re-projections if we need to reposition ourself
|
||||
// and lets us know how many points are in the shape.
|
||||
std::vector<vertex2d> path_positions;
|
||||
std::vector<double> path_distances; // distance from node x-1 to node x
|
||||
double total_distance = 0;
|
||||
|
||||
|
||||
shape_path.rewind(0);
|
||||
while (!agg::is_stop(cmd = shape_path.vertex(&new_x,&new_y))) //For each node in the shape
|
||||
{
|
||||
|
@ -422,32 +456,32 @@ p.minimum_distance)))
|
|||
}
|
||||
//Now path_positions is full and total_distance is correct
|
||||
//shape_path shouldn't be used from here
|
||||
|
||||
|
||||
double distance = 0.0;
|
||||
std::pair<double, double> string_dimensions = p.info.get_dimensions();
|
||||
|
||||
|
||||
double string_width = string_dimensions.first;
|
||||
|
||||
|
||||
double displacement = boost::tuples::get<1>(p.displacement_); // displace by dy
|
||||
|
||||
|
||||
//Calculate a target_distance that will place the labels centered evenly rather than offset from the start of the linestring
|
||||
if (total_distance < string_width) //Can't place any strings
|
||||
return;
|
||||
|
||||
|
||||
//If there is no spacing then just do one label, otherwise calculate how many there should be
|
||||
int num_labels = 1;
|
||||
if (p.label_spacing > 0)
|
||||
num_labels = static_cast<int> (floor(total_distance / (p.label_spacing + string_width)));
|
||||
|
||||
|
||||
if (p.force_odd_labels && num_labels%2 == 0)
|
||||
num_labels--;
|
||||
if (num_labels <= 0)
|
||||
num_labels = 1;
|
||||
|
||||
|
||||
//Now we know how many labels we are going to place, calculate the spacing so that they will get placed evenly
|
||||
double spacing = total_distance / num_labels;
|
||||
double target_distance = (spacing - string_width) / 2; // first label should be placed at half the spacing
|
||||
|
||||
|
||||
//Calculate or read out the tolerance
|
||||
double tolerance_delta, tolerance;
|
||||
if (p.label_position_tolerance > 0)
|
||||
|
@ -473,12 +507,12 @@ p.minimum_distance)))
|
|||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
//Add the length of this segment to the total we have saved up
|
||||
double segment_length = path_distances[index];
|
||||
distance += segment_length;
|
||||
|
||||
|
||||
//While we have enough distance to place text in
|
||||
while (distance > target_distance)
|
||||
{
|
||||
|
@ -489,11 +523,11 @@ p.minimum_distance)))
|
|||
//Record details for the start of the string placement
|
||||
int orientation = 0;
|
||||
std::auto_ptr<placement_element> current_placement = get_placement_offset(p, path_positions, path_distances, orientation, index, segment_length - (distance - target_distance) + (diff*dir));
|
||||
|
||||
|
||||
//We were unable to place here
|
||||
if (current_placement.get() == NULL)
|
||||
continue;
|
||||
|
||||
|
||||
//Apply displacement
|
||||
//NOTE: The text is centered on the line in get_placement_offset, so we are offsetting from there
|
||||
if (displacement != 0)
|
||||
|
@ -506,7 +540,7 @@ p.minimum_distance)))
|
|||
anglesum += current_placement->nodes_[i].angle;
|
||||
}
|
||||
anglesum /= current_placement->nodes_.size(); //Now it is angle average
|
||||
|
||||
|
||||
//Offset all the characters by this angle
|
||||
for (unsigned i = 0; i < current_placement->nodes_.size(); i++)
|
||||
{
|
||||
|
@ -514,14 +548,14 @@ p.minimum_distance)))
|
|||
current_placement->nodes_[i].y += displacement*sin(anglesum+M_PI/2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool status = test_placement(p, current_placement, orientation);
|
||||
|
||||
|
||||
if (status) //We have successfully placed one
|
||||
{
|
||||
p.placements.push_back(current_placement.release());
|
||||
update_detector(p);
|
||||
|
||||
|
||||
//Totally break out of the loops
|
||||
diff = tolerance;
|
||||
break;
|
||||
|
@ -532,23 +566,23 @@ p.minimum_distance)))
|
|||
while (!p.envelopes.empty())
|
||||
p.envelopes.pop();
|
||||
}
|
||||
|
||||
|
||||
//Don't need to loop twice when diff = 0
|
||||
if (diff == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
distance -= target_distance; //Consume the spacing gap we have used up
|
||||
target_distance = spacing; //Need to reset the target_distance as it is spacing/2 for the first label.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
std::auto_ptr<placement_element> placement_finder<DetectorT>::get_placement_offset(placement & p, const std::vector<vertex2d> &path_positions, const std::vector<double> &path_distances, int &orientation, unsigned index, double distance)
|
||||
{
|
||||
|
@ -560,7 +594,7 @@ p.minimum_distance)))
|
|||
}
|
||||
if (index <= 1 && distance < 0) //We've gone off the start, fail out
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
|
||||
|
||||
//Same thing, checking if we go off the end
|
||||
while (index < path_distances.size() && distance > path_distances[index])
|
||||
{
|
||||
|
@ -569,46 +603,46 @@ p.minimum_distance)))
|
|||
}
|
||||
if (index >= path_distances.size())
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
|
||||
|
||||
//Keep track of the initial index,distance incase we need to re-call get_placement_offset
|
||||
const unsigned initial_index = index;
|
||||
const double initial_distance = distance;
|
||||
|
||||
|
||||
std::auto_ptr<placement_element> current_placement(new placement_element);
|
||||
|
||||
double string_height = p.info.get_dimensions().second;
|
||||
double old_x = path_positions[index-1].x;
|
||||
double old_y = path_positions[index-1].y;
|
||||
|
||||
|
||||
double new_x = path_positions[index].x;
|
||||
double new_y = path_positions[index].y;
|
||||
|
||||
|
||||
double dx = new_x - old_x;
|
||||
double dy = new_y - old_y;
|
||||
|
||||
|
||||
double segment_length = path_distances[index];
|
||||
if (segment_length == 0) {
|
||||
// Not allowed to place across on 0 length segments or discontinuities
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
}
|
||||
|
||||
|
||||
current_placement->starting_x = old_x + dx*distance/segment_length;
|
||||
current_placement->starting_y = old_y + dy*distance/segment_length;
|
||||
double angle = atan2(-dy, dx);
|
||||
|
||||
|
||||
bool orientation_forced = (orientation != 0); //Wether the orientation was set by the caller
|
||||
if (!orientation_forced)
|
||||
orientation = (angle > 0.55*M_PI || angle < -0.45*M_PI) ? -1 : 1;
|
||||
|
||||
|
||||
unsigned upside_down_char_count = 0; //Count of characters that are placed upside down.
|
||||
|
||||
|
||||
for (unsigned i = 0; i < p.info.num_characters(); ++i)
|
||||
{
|
||||
character_info ci;
|
||||
unsigned c;
|
||||
|
||||
|
||||
double last_character_angle = angle;
|
||||
|
||||
|
||||
// grab the next character according to the orientation
|
||||
ci = orientation > 0 ? p.info.at(i) : p.info.at(p.info.num_characters() - i - 1);
|
||||
c = ci.character;
|
||||
|
@ -623,12 +657,12 @@ p.minimum_distance)))
|
|||
//Coordinates this character ends at, calculated below
|
||||
double end_x = 0;
|
||||
double end_y = 0;
|
||||
|
||||
if (segment_length - distance >= ci.width)
|
||||
|
||||
if (segment_length - distance >= ci.width)
|
||||
{
|
||||
//if the distance remaining in this segment is enough, we just go further along the segment
|
||||
distance += ci.width;
|
||||
|
||||
|
||||
end_x = old_x + dx*distance/segment_length;
|
||||
end_y = old_y + dy*distance/segment_length;
|
||||
}
|
||||
|
@ -650,24 +684,24 @@ p.minimum_distance)))
|
|||
new_y = path_positions[index].y;
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
|
||||
segment_length = path_distances[index];
|
||||
}
|
||||
while (std::sqrt(std::pow(start_x - new_x, 2) + std::pow(start_y - new_y, 2)) < ci.width); //Distance from start_ to new_
|
||||
|
||||
|
||||
//Calculate the position to place the end of the character on
|
||||
find_line_circle_intersection(
|
||||
start_x, start_y, ci.width,
|
||||
old_x, old_y, new_x, new_y,
|
||||
start_x, start_y, ci.width,
|
||||
old_x, old_y, new_x, new_y,
|
||||
end_x, end_y); //results are stored in end_x, end_y
|
||||
|
||||
//Need to calculate distance on the new segment
|
||||
distance = std::sqrt(std::pow(old_x - end_x, 2) + std::pow(old_y - end_y, 2));
|
||||
}
|
||||
|
||||
|
||||
//Calculate angle from the start of the character to the end based on start_/end_ position
|
||||
angle = atan2(start_y-end_y, end_x-start_x);
|
||||
|
||||
|
||||
//Test last_character_angle vs angle
|
||||
// since our rendering angle has changed then check against our
|
||||
// max allowable angle change.
|
||||
|
@ -677,22 +711,22 @@ p.minimum_distance)))
|
|||
angle_delta -= 2*M_PI;
|
||||
while (angle_delta < -M_PI)
|
||||
angle_delta += 2*M_PI;
|
||||
if (p.max_char_angle_delta > 0 &&
|
||||
if (p.max_char_angle_delta > 0 &&
|
||||
fabs(angle_delta) > p.max_char_angle_delta*(M_PI/180))
|
||||
{
|
||||
//std::clog << "FAIL: Too Bendy!" << std::endl;
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
}
|
||||
|
||||
|
||||
double render_angle = angle;
|
||||
|
||||
|
||||
double render_x = start_x;
|
||||
double render_y = start_y;
|
||||
|
||||
|
||||
//Center the text on the line
|
||||
render_x -= (((double)string_height/2.0) - 1.0)*cos(render_angle+M_PI/2);
|
||||
render_y += (((double)string_height/2.0) - 1.0)*sin(render_angle+M_PI/2);
|
||||
|
||||
|
||||
if (orientation < 0)
|
||||
{
|
||||
// rotate in place
|
||||
|
@ -700,21 +734,21 @@ p.minimum_distance)))
|
|||
render_y -= ci.width*sin(render_angle) + (string_height-2)*cos(render_angle);
|
||||
render_angle += M_PI;
|
||||
}
|
||||
current_placement->add_node(c,render_x - current_placement->starting_x,
|
||||
-render_y + current_placement->starting_y,
|
||||
current_placement->add_node(c,render_x - current_placement->starting_x,
|
||||
-render_y + current_placement->starting_y,
|
||||
render_angle);
|
||||
|
||||
|
||||
//Normalise to 0 <= angle < 2PI
|
||||
while (render_angle >= 2*M_PI)
|
||||
render_angle -= 2*M_PI;
|
||||
while (render_angle < 0)
|
||||
render_angle += 2*M_PI;
|
||||
|
||||
|
||||
if (render_angle > M_PI/2 && render_angle < 1.5*M_PI)
|
||||
upside_down_char_count++;
|
||||
}
|
||||
|
||||
//If we placed too many characters upside down
|
||||
|
||||
//If we placed too many characters upside down
|
||||
if (upside_down_char_count >= p.info.num_characters()/2.0)
|
||||
{
|
||||
//if we auto-detected the orientation then retry with the opposite orientation
|
||||
|
@ -730,15 +764,15 @@ p.minimum_distance)))
|
|||
return std::auto_ptr<placement_element>(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return current_placement;
|
||||
}
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
bool placement_finder<DetectorT>::test_placement(placement & p, const std::auto_ptr<placement_element> & current_placement, const int & orientation)
|
||||
{
|
||||
std::pair<double, double> string_dimensions = p.info.get_dimensions();
|
||||
|
||||
|
||||
double string_height = string_dimensions.second;
|
||||
|
||||
|
||||
|
@ -769,15 +803,15 @@ p.minimum_distance)))
|
|||
else
|
||||
{
|
||||
// put four corners of the letter into envelope
|
||||
e.init(x, y, x + ci.width*cos(angle),
|
||||
e.init(x, y, x + ci.width*cos(angle),
|
||||
y - ci.width*sin(angle));
|
||||
e.expand_to_include(x - ci.height*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)),
|
||||
e.expand_to_include(x + (ci.width*cos(angle) - ci.height*sin(angle)),
|
||||
y - (ci.width*sin(angle) + ci.height*cos(angle)));
|
||||
}
|
||||
|
||||
if (!dimensions_.intersects(e) ||
|
||||
|
||||
if (!dimensions_.intersects(e) ||
|
||||
!detector_.has_placement(e, p.info.get_string(), p.minimum_distance))
|
||||
{
|
||||
//std::clog << "No Intersects:" << !dimensions_.intersects(e) << ": " << e << " @ " << dimensions_ << std::endl;
|
||||
|
@ -785,7 +819,7 @@ p.minimum_distance)))
|
|||
status = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (p.avoid_edges && !dimensions_.contains(e))
|
||||
{
|
||||
//std::clog << "Fail avoid edges" << std::endl;
|
||||
|
@ -795,25 +829,25 @@ p.minimum_distance)))
|
|||
|
||||
p.envelopes.push(e);
|
||||
}
|
||||
|
||||
|
||||
current_placement->rewind();
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
template <typename DetectorT>
|
||||
void placement_finder<DetectorT>::find_line_circle_intersection(
|
||||
const double &cx, const double &cy, const double &radius,
|
||||
const double &x1, const double &y1, const double &x2, const double &y2,
|
||||
const double &cx, const double &cy, const double &radius,
|
||||
const double &x1, const double &y1, const double &x2, const double &y2,
|
||||
double &ix, double &iy)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
|
||||
double A = dx * dx + dy * dy;
|
||||
double B = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
|
||||
double C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - radius * radius;
|
||||
|
||||
|
||||
double det = B * B - 4 * A * C;
|
||||
if (A <= 0.0000001 || det < 0)
|
||||
{
|
||||
|
@ -833,17 +867,17 @@ p.minimum_distance)))
|
|||
else
|
||||
{
|
||||
//Two solutions.
|
||||
|
||||
|
||||
//Always use the 1st one
|
||||
//We only really have one solution here, as we know the line segment will start in the circle and end outside
|
||||
double t = (-B + std::sqrt(det)) / (2 * A);
|
||||
ix = x1 + t * dx;
|
||||
iy = y1 + t * dy;
|
||||
|
||||
|
||||
//t = (-B - std::sqrt(det)) / (2 * A);
|
||||
//ix = x1 + t * dx;
|
||||
//iy = y1 + t * dy;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -864,12 +898,12 @@ p.minimum_distance)))
|
|||
{
|
||||
detector_.clear();
|
||||
}
|
||||
|
||||
|
||||
typedef coord_transform2<CoordTransform,geometry2d> PathType;
|
||||
typedef label_collision_detector4 DetectorType;
|
||||
|
||||
|
||||
template class placement_finder<DetectorType>;
|
||||
template void placement_finder<DetectorType>::find_point_placements<PathType> (placement&, PathType & );
|
||||
template void placement_finder<DetectorType>::find_line_placements<PathType> (placement&, PathType & );
|
||||
|
||||
|
||||
} // namespace
|
||||
|
|
124
src/save_map.cpp
124
src/save_map.cpp
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -36,7 +36,7 @@
|
|||
// stl
|
||||
#include <iostream>
|
||||
|
||||
namespace mapnik
|
||||
namespace mapnik
|
||||
{
|
||||
using boost::property_tree::ptree;
|
||||
using boost::optional;
|
||||
|
@ -44,7 +44,7 @@ namespace mapnik
|
|||
class serialize_symbolizer : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
serialize_symbolizer( ptree & r , bool explicit_defaults):
|
||||
serialize_symbolizer( ptree & r , bool explicit_defaults):
|
||||
rule_(r),
|
||||
explicit_defaults_(explicit_defaults) {}
|
||||
|
||||
|
@ -65,23 +65,23 @@ namespace mapnik
|
|||
|
||||
if ( strk.get_color() != dfl.get_color() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "stroke", strk.get_color() );
|
||||
set_css( sym_node, "stroke", strk.get_color() );
|
||||
}
|
||||
if ( strk.get_width() != dfl.get_width() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "stroke-width", strk.get_width() );
|
||||
set_css( sym_node, "stroke-width", strk.get_width() );
|
||||
}
|
||||
if ( strk.get_opacity() != dfl.get_opacity() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "stroke-opacity", strk.get_opacity() );
|
||||
set_css( sym_node, "stroke-opacity", strk.get_opacity() );
|
||||
}
|
||||
if ( strk.get_line_join() != dfl.get_line_join() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "stroke-linejoin", strk.get_line_join() );
|
||||
set_css( sym_node, "stroke-linejoin", strk.get_line_join() );
|
||||
}
|
||||
if ( strk.get_line_cap() != dfl.get_line_cap() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "stroke-linecap", strk.get_line_cap() );
|
||||
set_css( sym_node, "stroke-linecap", strk.get_line_cap() );
|
||||
}
|
||||
if ( ! strk.get_dash_array().empty() )
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ namespace mapnik
|
|||
os << dashes[i].first << ", " << dashes[i].second;
|
||||
if ( i + 1 < dashes.size() ) os << ", ";
|
||||
}
|
||||
set_css( sym_node, "stroke-dasharray", os.str() );
|
||||
set_css( sym_node, "stroke-dasharray", os.str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,11 +112,11 @@ namespace mapnik
|
|||
|
||||
if ( sym.get_fill() != dfl.get_fill() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "fill", sym.get_fill() );
|
||||
set_css( sym_node, "fill", sym.get_fill() );
|
||||
}
|
||||
if ( sym.get_opacity() != dfl.get_opacity() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "fill-opacity", sym.get_opacity() );
|
||||
set_css( sym_node, "fill-opacity", sym.get_opacity() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,20 @@ namespace mapnik
|
|||
|
||||
add_font_attributes( sym_node, sym);
|
||||
add_image_attributes( sym_node, sym);
|
||||
|
||||
// pseudo-default-construct a shield_symbolizer. It is used
|
||||
// to avoid printing of attributes with default values without
|
||||
// repeating the default values here.
|
||||
// maybe add a real, explicit default-ctor?
|
||||
shield_symbolizer sym_dfl("<no default>", "<no default>", 0, color(0,0,0), "<no default>", "<no default>", 0, 0 );
|
||||
if (sym.get_unlock_image() != sym_dfl.get_unlock_image() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( sym_node, "unlock_image", sym.get_unlock_image() );
|
||||
}
|
||||
if (sym.get_no_text() != sym_dfl.get_no_text() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( sym_node, "no_text", sym.get_no_text() );
|
||||
}
|
||||
}
|
||||
|
||||
void operator () ( const text_symbolizer & sym )
|
||||
|
@ -177,15 +191,15 @@ namespace mapnik
|
|||
|
||||
if ( sym.get_fill() != dfl.get_fill() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "fill", sym.get_fill() );
|
||||
set_css( sym_node, "fill", sym.get_fill() );
|
||||
}
|
||||
if ( sym.get_opacity() != dfl.get_opacity() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "fill-opacity", sym.get_opacity() );
|
||||
set_css( sym_node, "fill-opacity", sym.get_opacity() );
|
||||
}
|
||||
if ( sym.height() != dfl.height() || explicit_defaults_ )
|
||||
{
|
||||
set_css( sym_node, "height", sym.height() );
|
||||
set_css( sym_node, "height", sym.height() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,22 +235,22 @@ namespace mapnik
|
|||
{
|
||||
const std::string & name = sym.get_name();
|
||||
if ( ! name.empty() ) {
|
||||
set_attr( node, "name", name );
|
||||
set_attr( node, "name", name );
|
||||
}
|
||||
const std::string & face_name = sym.get_face_name();
|
||||
if ( ! face_name.empty() ) {
|
||||
set_attr( node, "face_name", face_name );
|
||||
set_attr( node, "face_name", face_name );
|
||||
}
|
||||
const std::string & fontset_name = sym.get_fontset().get_name();
|
||||
if ( ! fontset_name.empty() ) {
|
||||
set_attr( node, "fontset_name", fontset_name );
|
||||
}
|
||||
|
||||
set_attr( node, "size", sym.get_text_size() );
|
||||
set_attr( node, "fill", sym.get_fill() );
|
||||
set_attr( node, "size", sym.get_text_size() );
|
||||
set_attr( node, "fill", sym.get_fill() );
|
||||
|
||||
// pseudo-default-construct a text_symbolizer. It is used
|
||||
// to avoid printing ofattributes with default values without
|
||||
// to avoid printing ofattributes with default values without
|
||||
// repeating the default values here.
|
||||
// maybe add a real, explicit default-ctor?
|
||||
text_symbolizer dfl("<no default>", "<no default>",
|
||||
|
@ -245,39 +259,43 @@ namespace mapnik
|
|||
position displacement = sym.get_displacement();
|
||||
if ( displacement.get<0>() != dfl.get_displacement().get<0>() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "dx", displacement.get<0>() );
|
||||
set_attr( node, "dx", displacement.get<0>() );
|
||||
}
|
||||
if ( displacement.get<1>() != dfl.get_displacement().get<1>() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "dy", displacement.get<1>() );
|
||||
set_attr( node, "dy", displacement.get<1>() );
|
||||
}
|
||||
|
||||
if (sym.get_label_placement() != dfl.get_label_placement() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "placement", sym.get_label_placement() );
|
||||
set_attr( node, "placement", sym.get_label_placement() );
|
||||
}
|
||||
|
||||
|
||||
if (sym.get_vertical_alignment() != dfl.get_vertical_alignment() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "vertical_alignment", sym.get_vertical_alignment() );
|
||||
set_attr( node, "vertical_alignment", sym.get_vertical_alignment() );
|
||||
}
|
||||
|
||||
|
||||
if (sym.get_halo_radius() != dfl.get_halo_radius() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "halo_radius", sym.get_halo_radius() );
|
||||
set_attr( node, "halo_radius", sym.get_halo_radius() );
|
||||
}
|
||||
const color & c = sym.get_halo_fill();
|
||||
if ( c != dfl.get_halo_fill() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "halo_fill", c );
|
||||
set_attr( node, "halo_fill", c );
|
||||
}
|
||||
if (sym.get_text_ratio() != dfl.get_text_ratio() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "text_ratio", sym.get_text_ratio() );
|
||||
set_attr( node, "text_ratio", sym.get_text_ratio() );
|
||||
}
|
||||
if (sym.get_wrap_width() != dfl.get_wrap_width() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "wrap_width", sym.get_wrap_width() );
|
||||
set_attr( node, "wrap_width", sym.get_wrap_width() );
|
||||
}
|
||||
if (sym.get_wrap_before() != dfl.get_wrap_before() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "wrap_before", sym.get_wrap_before() );
|
||||
}
|
||||
if (sym.get_wrap_char() != dfl.get_wrap_char() || explicit_defaults_ )
|
||||
{
|
||||
|
@ -289,27 +307,39 @@ namespace mapnik
|
|||
}
|
||||
if (sym.get_line_spacing() != dfl.get_line_spacing() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "line_spacing", sym.get_line_spacing() );
|
||||
set_attr( node, "line_spacing", sym.get_line_spacing() );
|
||||
}
|
||||
if (sym.get_character_spacing() != dfl.get_character_spacing() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "character_spacing", sym.get_character_spacing() );
|
||||
set_attr( node, "character_spacing", sym.get_character_spacing() );
|
||||
}
|
||||
if (sym.get_label_spacing() != dfl.get_label_spacing() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "spacing", sym.get_label_spacing() );
|
||||
set_attr( node, "spacing", sym.get_label_spacing() );
|
||||
}
|
||||
if (sym.get_minimum_distance() != dfl.get_minimum_distance() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "min_distance", sym.get_minimum_distance() );
|
||||
set_attr( node, "min_distance", sym.get_minimum_distance() );
|
||||
}
|
||||
if (sym.get_allow_overlap() != dfl.get_allow_overlap() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "allow_overlap", sym.get_allow_overlap() );
|
||||
set_attr( node, "allow_overlap", sym.get_allow_overlap() );
|
||||
}
|
||||
if (sym.get_avoid_edges() != dfl.get_avoid_edges() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "avoid_edges", sym.get_avoid_edges() );
|
||||
set_attr( node, "avoid_edges", sym.get_avoid_edges() );
|
||||
}
|
||||
if (sym.get_opacity() != dfl.get_opacity() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "opacity", sym.get_opacity() );
|
||||
}
|
||||
if (sym.get_horizontal_alignment() != dfl.get_horizontal_alignment() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "horizontal_alignment", sym.get_horizontal_alignment() );
|
||||
}
|
||||
if (sym.get_justify_alignment() != dfl.get_justify_alignment() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( node, "justify_alignment", sym.get_justify_alignment() );
|
||||
}
|
||||
}
|
||||
ptree & rule_;
|
||||
|
@ -320,7 +350,7 @@ namespace mapnik
|
|||
{
|
||||
ptree & rule_node = style_node.push_back(
|
||||
ptree::value_type("Rule", ptree() ))->second;
|
||||
|
||||
|
||||
rule_type dfl;
|
||||
if ( rule.get_name() != dfl.get_name() )
|
||||
{
|
||||
|
@ -372,7 +402,7 @@ namespace mapnik
|
|||
{
|
||||
const feature_type_style & style = style_it->second;
|
||||
const std::string & name = style_it->first;
|
||||
|
||||
|
||||
ptree & style_node = map_node.push_back(
|
||||
ptree::value_type("Style", ptree()))->second;
|
||||
|
||||
|
@ -382,7 +412,7 @@ namespace mapnik
|
|||
rules::const_iterator end = style.get_rules().end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
serialize_rule( style_node, * it , explicit_defaults);
|
||||
serialize_rule( style_node, * it , explicit_defaults);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -418,15 +448,15 @@ namespace mapnik
|
|||
for (; it != end; ++it)
|
||||
{
|
||||
boost::property_tree::ptree & param_node = datasource_node.push_back(
|
||||
boost::property_tree::ptree::value_type("Parameter",
|
||||
boost::property_tree::ptree::value_type("Parameter",
|
||||
boost::property_tree::ptree()))->second;
|
||||
param_node.put("<xmlattr>.name", it->first );
|
||||
param_node.put_own( it->second );
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void serialize_layer( ptree & map_node, const Layer & layer )
|
||||
void serialize_layer( ptree & map_node, const Layer & layer )
|
||||
{
|
||||
ptree & layer_node = map_node.push_back(
|
||||
ptree::value_type("Layer", ptree()))->second;
|
||||
|
@ -449,7 +479,7 @@ namespace mapnik
|
|||
{
|
||||
set_attr( layer_node, "srs", layer.srs() );
|
||||
}
|
||||
|
||||
|
||||
set_attr/*<bool>*/( layer_node, "status", layer.isActive() );
|
||||
set_attr/*<bool>*/( layer_node, "clear_label_cache", layer.clear_label_cache() );
|
||||
|
||||
|
@ -467,7 +497,7 @@ namespace mapnik
|
|||
{
|
||||
set_attr( layer_node, "queryable", layer.isQueryable() );
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> const& style_names = layer.styles();
|
||||
for (unsigned i = 0; i < style_names.size(); ++i)
|
||||
{
|
||||
|
@ -490,11 +520,11 @@ namespace mapnik
|
|||
ptree & map_node = pt.push_back(ptree::value_type("Map", ptree() ))->second;
|
||||
|
||||
set_attr( map_node, "srs", map.srs() );
|
||||
|
||||
|
||||
optional<color> c = map.background();
|
||||
if ( c )
|
||||
{
|
||||
set_attr( map_node, "bgcolor", * c );
|
||||
set_attr( map_node, "bgcolor", * c );
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -517,9 +547,9 @@ namespace mapnik
|
|||
for (unsigned i = 0; i < layers.size(); ++i )
|
||||
{
|
||||
serialize_layer( map_node, layers[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void save_map(Map const & map, std::string const& filename, bool explicit_defaults)
|
||||
{
|
||||
ptree pt;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -38,25 +38,49 @@ namespace mapnik
|
|||
std::string const& name,
|
||||
std::string const& face_name,
|
||||
unsigned size,
|
||||
color const& fill,
|
||||
color const& fill,
|
||||
std::string const& file,
|
||||
std::string const& type,
|
||||
unsigned width,unsigned height)
|
||||
: text_symbolizer(name, face_name, size, fill),
|
||||
symbolizer_with_image( file, type, width, height )
|
||||
symbolizer_with_image( file, type, width, height ),
|
||||
unlock_image_(false),
|
||||
no_text_(false)
|
||||
{
|
||||
}
|
||||
|
||||
shield_symbolizer::shield_symbolizer(
|
||||
std::string const& name,
|
||||
unsigned size,
|
||||
color const& fill,
|
||||
color const& fill,
|
||||
std::string const& file,
|
||||
std::string const& type,
|
||||
unsigned width,unsigned height)
|
||||
: text_symbolizer(name, size, fill),
|
||||
symbolizer_with_image( file, type, width, height )
|
||||
symbolizer_with_image( file, type, width, height ),
|
||||
unlock_image_(false),
|
||||
no_text_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void shield_symbolizer::set_unlock_image(bool unlock_image)
|
||||
{
|
||||
unlock_image_ = unlock_image;
|
||||
}
|
||||
|
||||
bool shield_symbolizer::get_unlock_image() const
|
||||
{
|
||||
return unlock_image_;
|
||||
}
|
||||
|
||||
void shield_symbolizer::set_no_text(bool no_text)
|
||||
{
|
||||
no_text_ = no_text;
|
||||
}
|
||||
|
||||
bool shield_symbolizer::get_no_text() const
|
||||
{
|
||||
return no_text_;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2006 Artem Pavlenko
|
||||
|
@ -32,6 +32,7 @@
|
|||
static const char * label_placement_strings[] = {
|
||||
"point",
|
||||
"line",
|
||||
"vertex",
|
||||
""
|
||||
};
|
||||
|
||||
|
@ -48,6 +49,26 @@ static const char * vertical_alignment_strings[] = {
|
|||
|
||||
IMPLEMENT_ENUM( mapnik::vertical_alignment_e, vertical_alignment_strings );
|
||||
|
||||
static const char * horizontal_alignment_strings[] = {
|
||||
"left",
|
||||
"middle",
|
||||
"right",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_ENUM( mapnik::horizontal_alignment_e, horizontal_alignment_strings );
|
||||
|
||||
static const char * justify_alignment_strings[] = {
|
||||
"left",
|
||||
"middle",
|
||||
"right",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_ENUM( mapnik::justify_alignment_e, justify_alignment_strings );
|
||||
|
||||
static const char * text_convert_strings[] = {
|
||||
"none",
|
||||
"toupper",
|
||||
|
@ -85,7 +106,12 @@ namespace mapnik
|
|||
displacement_(0.0,0.0),
|
||||
avoid_edges_(false),
|
||||
minimum_distance_(0.0),
|
||||
overlap_(false) {}
|
||||
overlap_(false),
|
||||
opacity_(1.0),
|
||||
wrap_before_(false),
|
||||
halign_(H_MIDDLE),
|
||||
jalign_(J_MIDDLE) {}
|
||||
|
||||
text_symbolizer::text_symbolizer(std::string const& name, unsigned size, color const& fill)
|
||||
: name_(name),
|
||||
//face_name_(""),
|
||||
|
@ -110,7 +136,12 @@ namespace mapnik
|
|||
displacement_(0.0,0.0),
|
||||
avoid_edges_(false),
|
||||
minimum_distance_(0.0),
|
||||
overlap_(false) {}
|
||||
overlap_(false),
|
||||
opacity_(1.0),
|
||||
wrap_before_(false),
|
||||
halign_(H_MIDDLE),
|
||||
jalign_(J_MIDDLE) {}
|
||||
|
||||
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
||||
: name_(rhs.name_),
|
||||
face_name_(rhs.face_name_),
|
||||
|
@ -135,8 +166,12 @@ namespace mapnik
|
|||
displacement_(rhs.displacement_),
|
||||
avoid_edges_(rhs.avoid_edges_),
|
||||
minimum_distance_(rhs.minimum_distance_),
|
||||
overlap_(rhs.overlap_) {}
|
||||
|
||||
overlap_(rhs.overlap_),
|
||||
opacity_(rhs.opacity_),
|
||||
wrap_before_(rhs.wrap_before_),
|
||||
halign_(rhs.halign_),
|
||||
jalign_(rhs.jalign_) {}
|
||||
|
||||
text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
||||
{
|
||||
if (this == &other)
|
||||
|
@ -161,28 +196,32 @@ namespace mapnik
|
|||
label_p_ = other.label_p_;
|
||||
valign_ = other.valign_;
|
||||
anchor_ = other.anchor_;
|
||||
displacement_ = other.displacement_;
|
||||
displacement_ = other.displacement_;
|
||||
avoid_edges_ = other.avoid_edges_;
|
||||
minimum_distance_ = other.minimum_distance_;
|
||||
overlap_ = other.overlap_;
|
||||
opacity_ = other.opacity_;
|
||||
wrap_before_ = other.wrap_before_;
|
||||
halign_ = other.halign_;
|
||||
jalign_ = other.jalign_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string const& text_symbolizer::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_name(std::string name)
|
||||
{
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
|
||||
std::string const& text_symbolizer::get_face_name() const
|
||||
{
|
||||
return face_name_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_face_name(std::string face_name)
|
||||
{
|
||||
face_name_ = face_name;
|
||||
|
@ -203,7 +242,7 @@ namespace mapnik
|
|||
return text_ratio_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_text_ratio(unsigned ratio)
|
||||
void text_symbolizer::set_text_ratio(unsigned ratio)
|
||||
{
|
||||
text_ratio_ = ratio;
|
||||
}
|
||||
|
@ -213,10 +252,20 @@ namespace mapnik
|
|||
return wrap_width_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_width(unsigned width)
|
||||
void text_symbolizer::set_wrap_width(unsigned width)
|
||||
{
|
||||
wrap_width_ = width;
|
||||
}
|
||||
}
|
||||
|
||||
bool text_symbolizer::get_wrap_before() const
|
||||
{
|
||||
return wrap_before_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_before(bool wrap_before)
|
||||
{
|
||||
wrap_before_ = wrap_before;
|
||||
}
|
||||
|
||||
unsigned char text_symbolizer::get_wrap_char() const
|
||||
{
|
||||
|
@ -228,16 +277,16 @@ namespace mapnik
|
|||
return std::string(1, wrap_char_);
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_char(unsigned char character)
|
||||
void text_symbolizer::set_wrap_char(unsigned char character)
|
||||
{
|
||||
wrap_char_ = character;
|
||||
}
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_char_from_string(std::string character)
|
||||
void text_symbolizer::set_wrap_char_from_string(std::string character)
|
||||
{
|
||||
wrap_char_ = (character)[0];
|
||||
}
|
||||
|
||||
|
||||
text_convert_e text_symbolizer::get_text_convert() const
|
||||
{
|
||||
return text_convert_;
|
||||
|
@ -253,7 +302,7 @@ namespace mapnik
|
|||
return line_spacing_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_line_spacing(unsigned spacing)
|
||||
void text_symbolizer::set_line_spacing(unsigned spacing)
|
||||
{
|
||||
line_spacing_ = spacing;
|
||||
}
|
||||
|
@ -263,7 +312,7 @@ namespace mapnik
|
|||
return character_spacing_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_character_spacing(unsigned spacing)
|
||||
void text_symbolizer::set_character_spacing(unsigned spacing)
|
||||
{
|
||||
character_spacing_ = spacing;
|
||||
}
|
||||
|
@ -273,7 +322,7 @@ namespace mapnik
|
|||
return label_spacing_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_label_spacing(unsigned spacing)
|
||||
void text_symbolizer::set_label_spacing(unsigned spacing)
|
||||
{
|
||||
label_spacing_ = spacing;
|
||||
}
|
||||
|
@ -293,7 +342,7 @@ namespace mapnik
|
|||
return force_odd_labels_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_force_odd_labels(bool force)
|
||||
void text_symbolizer::set_force_odd_labels(bool force)
|
||||
{
|
||||
force_odd_labels_ = force;
|
||||
}
|
||||
|
@ -303,7 +352,7 @@ namespace mapnik
|
|||
return max_char_angle_delta_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_max_char_angle_delta(double angle)
|
||||
void text_symbolizer::set_max_char_angle_delta(double angle)
|
||||
{
|
||||
max_char_angle_delta_ = angle;
|
||||
}
|
||||
|
@ -322,12 +371,12 @@ namespace mapnik
|
|||
{
|
||||
fill_ = fill;
|
||||
}
|
||||
|
||||
|
||||
color const& text_symbolizer::get_fill() const
|
||||
{
|
||||
return fill_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_halo_fill(color const& fill)
|
||||
{
|
||||
halo_fill_ = fill;
|
||||
|
@ -337,22 +386,22 @@ namespace mapnik
|
|||
{
|
||||
return halo_fill_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_halo_radius(unsigned radius)
|
||||
{
|
||||
halo_radius_ = radius;
|
||||
}
|
||||
|
||||
|
||||
unsigned text_symbolizer::get_halo_radius() const
|
||||
{
|
||||
return halo_radius_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_label_placement(label_placement_e label_p)
|
||||
{
|
||||
label_p_ = label_p;
|
||||
}
|
||||
|
||||
|
||||
label_placement_e text_symbolizer::get_label_placement() const
|
||||
{
|
||||
return label_p_;
|
||||
|
@ -362,37 +411,37 @@ namespace mapnik
|
|||
{
|
||||
valign_ = valign;
|
||||
}
|
||||
|
||||
|
||||
vertical_alignment_e text_symbolizer::get_vertical_alignment() const
|
||||
{
|
||||
return valign_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_anchor(double x, double y)
|
||||
{
|
||||
anchor_ = boost::make_tuple(x,y);
|
||||
}
|
||||
|
||||
|
||||
position const& text_symbolizer::get_anchor() const
|
||||
{
|
||||
return anchor_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_displacement(double x, double y)
|
||||
{
|
||||
displacement_ = boost::make_tuple(x,y);
|
||||
}
|
||||
|
||||
|
||||
position const& text_symbolizer::get_displacement() const
|
||||
{
|
||||
return displacement_;
|
||||
}
|
||||
|
||||
|
||||
bool text_symbolizer::get_avoid_edges() const
|
||||
{
|
||||
return avoid_edges_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_avoid_edges(bool avoid)
|
||||
{
|
||||
avoid_edges_ = avoid;
|
||||
|
@ -402,7 +451,7 @@ namespace mapnik
|
|||
{
|
||||
return minimum_distance_;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_minimum_distance(double distance)
|
||||
{
|
||||
minimum_distance_ = distance;
|
||||
|
@ -412,9 +461,39 @@ namespace mapnik
|
|||
{
|
||||
overlap_ = overlap;
|
||||
}
|
||||
|
||||
|
||||
bool text_symbolizer::get_allow_overlap() const
|
||||
{
|
||||
return overlap_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_opacity(double opacity)
|
||||
{
|
||||
opacity_ = opacity;
|
||||
}
|
||||
|
||||
double text_symbolizer::get_opacity() const
|
||||
{
|
||||
return opacity_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_horizontal_alignment(horizontal_alignment_e halign)
|
||||
{
|
||||
halign_ = halign;
|
||||
}
|
||||
|
||||
horizontal_alignment_e text_symbolizer::get_horizontal_alignment() const
|
||||
{
|
||||
return halign_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_justify_alignment(justify_alignment_e jalign)
|
||||
{
|
||||
jalign_ = jalign;
|
||||
}
|
||||
|
||||
justify_alignment_e text_symbolizer::get_justify_alignment() const
|
||||
{
|
||||
return jalign_;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue