mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
Move font engine functions from .hpp to .cpp.
This commit is contained in:
parent
34405a5d9e
commit
5fd7035527
@ -174,7 +174,7 @@ public:
|
||||
|
||||
char_info character_dimensions(const unsigned c);
|
||||
|
||||
void get_string_info(string_info & info);
|
||||
void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);
|
||||
|
||||
void set_pixel_sizes(unsigned size)
|
||||
{
|
||||
@ -306,6 +306,18 @@ public:
|
||||
return face_set;
|
||||
}
|
||||
|
||||
face_set_ptr get_face_set(std::string const& name, font_set const& fset)
|
||||
{
|
||||
if (fset.size() > 0)
|
||||
{
|
||||
return get_face_set(fset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_face_set(name);
|
||||
}
|
||||
}
|
||||
|
||||
stroker_ptr get_stroker()
|
||||
{
|
||||
return stroker_;
|
||||
@ -323,21 +335,18 @@ struct text_renderer : private boost::noncopyable
|
||||
struct glyph_t : boost::noncopyable
|
||||
{
|
||||
FT_Glyph image;
|
||||
glyph_t(FT_Glyph image_) : image(image_) {}
|
||||
char_properties *properties;
|
||||
glyph_t(FT_Glyph image_, char_properties *properties_) : image(image_), properties(properties_) {}
|
||||
~glyph_t () { FT_Done_Glyph(image);}
|
||||
};
|
||||
|
||||
typedef boost::ptr_vector<glyph_t> glyphs_t;
|
||||
typedef T pixmap_type;
|
||||
|
||||
text_renderer (pixmap_type & pixmap, face_set_ptr faces, stroker & s)
|
||||
: pixmap_(pixmap),
|
||||
faces_(faces),
|
||||
stroker_(s),
|
||||
fill_(0,0,0),
|
||||
halo_fill_(255,255,255),
|
||||
halo_radius_(0.0),
|
||||
opacity_(1.0) {}
|
||||
text_renderer (pixmap_type & pixmap, face_set_ptr faces, stroker & s);
|
||||
box2d<double> prepare_glyphs(text_path *path);
|
||||
void render(double x0, double y0);
|
||||
void render_id(int feature_id,double x0, double y0, double min_radius=1.0);
|
||||
|
||||
|
||||
void set_pixel_size(unsigned size)
|
||||
@ -370,200 +379,8 @@ struct text_renderer : private boost::noncopyable
|
||||
opacity_=opacity;
|
||||
}
|
||||
|
||||
box2d<double> prepare_glyphs(text_path *path)
|
||||
{
|
||||
//clear glyphs
|
||||
glyphs_.clear();
|
||||
|
||||
FT_Matrix matrix;
|
||||
FT_Vector pen;
|
||||
FT_Error error;
|
||||
|
||||
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++)
|
||||
{
|
||||
int c;
|
||||
double x, y, angle;
|
||||
|
||||
path->vertex(&c, &x, &y, &angle);
|
||||
|
||||
#ifdef MAPNIK_DEBUG
|
||||
// TODO Enable when we have support for setting verbosity
|
||||
//std::clog << "prepare_glyphs: " << c << "," << x <<
|
||||
// "," << y << "," << angle << std::endl;
|
||||
#endif
|
||||
|
||||
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.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
continue;
|
||||
|
||||
error = FT_Get_Glyph(face->glyph, &image);
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
// take ownership of the glyph
|
||||
glyphs_.push_back(new glyph_t(image));
|
||||
}
|
||||
|
||||
return box2d<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.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.0 && halo_radius_ < 1024.0)
|
||||
{
|
||||
stroker_.init(halo_radius_);
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph g;
|
||||
error = FT_Glyph_Copy(pos->image, &g);
|
||||
if (!error)
|
||||
{
|
||||
FT_Glyph_Transform(g,0,&start);
|
||||
FT_Glyph_Stroke(&g,stroker_.get(),1);
|
||||
error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_NORMAL,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
|
||||
render_bitmap(&bit->bitmap, halo_fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(g);
|
||||
}
|
||||
}
|
||||
//render actual text
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
|
||||
FT_Glyph_Transform(pos->image,0,&start);
|
||||
|
||||
error = FT_Glyph_To_Bitmap( &(pos->image),FT_RENDER_MODE_NORMAL,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)pos->image;
|
||||
render_bitmap(&bit->bitmap, fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_id(int feature_id,double x0, double y0, double min_radius=1.0)
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Vector start;
|
||||
unsigned height = pixmap_.height();
|
||||
|
||||
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;
|
||||
|
||||
stroker_.init(std::max(halo_radius_,min_radius));
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph g;
|
||||
error = FT_Glyph_Copy(pos->image, &g);
|
||||
if (!error)
|
||||
{
|
||||
FT_Glyph_Transform(g,0,&start);
|
||||
FT_Glyph_Stroke(&g,stroker_.get(),1);
|
||||
error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_NORMAL,0,1);
|
||||
//error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_MONO,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
|
||||
render_bitmap_id(&bit->bitmap, feature_id,
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(g);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// unused currently, stroker is the new method for drawing halos
|
||||
/*
|
||||
void render_halo(FT_Bitmap *bitmap,unsigned rgba,int x,int y,int radius)
|
||||
{
|
||||
int x_max=x+bitmap->width;
|
||||
int y_max=y+bitmap->rows;
|
||||
int i,p,j,q;
|
||||
|
||||
for (i=x,p=0;i<x_max;++i,++p)
|
||||
{
|
||||
for (j=y,q=0;j<y_max;++j,++q)
|
||||
{
|
||||
int gray = bitmap->buffer[q*bitmap->width+p];
|
||||
if (gray)
|
||||
{
|
||||
for (int n=-halo_radius_; n <=halo_radius_; ++n)
|
||||
for (int m=-halo_radius_;m <= halo_radius_; ++m)
|
||||
pixmap_.blendPixel2(i+m,j+n,rgba,gray,opacity_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void render_bitmap(FT_Bitmap *bitmap,unsigned rgba,int x,int y)
|
||||
void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
|
||||
{
|
||||
int x_max=x+bitmap->width;
|
||||
int y_max=y+bitmap->rows;
|
||||
@ -576,7 +393,7 @@ private:
|
||||
int gray=bitmap->buffer[q*bitmap->width+p];
|
||||
if (gray)
|
||||
{
|
||||
pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
|
||||
pixmap_.blendPixel2(i, j, rgba, gray, opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,6 +428,7 @@ private:
|
||||
glyphs_t glyphs_;
|
||||
double opacity_;
|
||||
};
|
||||
typedef face_manager<freetype_engine> face_manager_freetype;
|
||||
}
|
||||
|
||||
#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
|
||||
|
||||
@ -139,7 +139,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
|
||||
metawriter_with_properties writer = sym.get_metawriter();
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
metawriter_with_properties writer = sym.get_metawriter();
|
||||
|
||||
BOOST_FOREACH( geometry_type * geom, geometries_to_process )
|
||||
|
||||
@ -1146,7 +1146,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
faces->set_character_sizes(placement_options->text_size);
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
|
||||
int w = (*marker)->width();
|
||||
int h = (*marker)->height();
|
||||
@ -1508,7 +1508,7 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
||||
string_info info(text);
|
||||
|
||||
faces->set_character_sizes(placement_options->text_size);
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
|
||||
@ -22,6 +22,9 @@
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/text_placements.hpp>
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@ -232,12 +235,13 @@ char_info font_face_set::character_dimensions(const unsigned c)
|
||||
FT_Done_Glyph(image);
|
||||
|
||||
unsigned tempx = face->glyph->advance.x >> 6;
|
||||
|
||||
char_info dim(c, tempx, glyph_bbox.yMax, glyph_bbox.yMin, face->size->metrics.height/64.0 /* >> 6 */);
|
||||
dimension_cache_.insert(std::pair<unsigned, char_info>(c, dim));
|
||||
return dim;
|
||||
}
|
||||
|
||||
void font_face_set::get_string_info(string_info & info)
|
||||
void font_face_set::get_string_info(string_info & info, UnicodeString const& ustr_unused, char_properties *format_unused)
|
||||
{
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
@ -286,8 +290,199 @@ void font_face_set::get_string_info(string_info & info)
|
||||
info.set_dimensions(width, height);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
text_renderer<T>::text_renderer (pixmap_type & pixmap, face_set_ptr faces, stroker & s)
|
||||
: pixmap_(pixmap),
|
||||
faces_(faces),
|
||||
stroker_(s),
|
||||
fill_(0,0,0),
|
||||
halo_fill_(255,255,255),
|
||||
halo_radius_(0.0),
|
||||
opacity_(1.0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
box2d<double> text_renderer<T>::prepare_glyphs(text_path *path)
|
||||
{
|
||||
//clear glyphs
|
||||
glyphs_.clear();
|
||||
|
||||
FT_Matrix matrix;
|
||||
FT_Vector pen;
|
||||
FT_Error error;
|
||||
|
||||
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++)
|
||||
{
|
||||
int c;
|
||||
double x, y, angle;
|
||||
|
||||
path->vertex(&c, &x, &y, &angle);
|
||||
|
||||
#ifdef MAPNIK_DEBUG
|
||||
// TODO Enable when we have support for setting verbosity
|
||||
//std::clog << "prepare_glyphs: " << c << "," << x <<
|
||||
// "," << y << "," << angle << std::endl;
|
||||
#endif
|
||||
|
||||
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.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
continue;
|
||||
|
||||
error = FT_Get_Glyph(face->glyph, &image);
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
// take ownership of the glyph
|
||||
glyphs_.push_back(new glyph_t(image, 0));
|
||||
}
|
||||
|
||||
return box2d<double>(bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void text_renderer<T>::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.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.0 && halo_radius_ < 1024.0)
|
||||
{
|
||||
stroker_.init(halo_radius_);
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph g;
|
||||
error = FT_Glyph_Copy(pos->image, &g);
|
||||
if (!error)
|
||||
{
|
||||
FT_Glyph_Transform(g,0,&start);
|
||||
FT_Glyph_Stroke(&g,stroker_.get(),1);
|
||||
error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_NORMAL,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
|
||||
render_bitmap(&bit->bitmap, halo_fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top, opacity_);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(g);
|
||||
}
|
||||
}
|
||||
//render actual text
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
|
||||
FT_Glyph_Transform(pos->image,0,&start);
|
||||
|
||||
error = FT_Glyph_To_Bitmap( &(pos->image),FT_RENDER_MODE_NORMAL,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)pos->image;
|
||||
render_bitmap(&bit->bitmap, fill_.rgba(),
|
||||
bit->left,
|
||||
height - bit->top, opacity_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void text_renderer<T>::render_id(int feature_id,double x0, double y0, double min_radius)
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Vector start;
|
||||
unsigned height = pixmap_.height();
|
||||
|
||||
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;
|
||||
|
||||
stroker_.init(std::max(halo_radius_,min_radius));
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph g;
|
||||
error = FT_Glyph_Copy(pos->image, &g);
|
||||
if (!error)
|
||||
{
|
||||
FT_Glyph_Transform(g,0,&start);
|
||||
FT_Glyph_Stroke(&g,stroker_.get(),1);
|
||||
error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_NORMAL,0,1);
|
||||
//error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_MONO,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
|
||||
render_bitmap_id(&bit->bitmap, feature_id,
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(g);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
boost::mutex freetype_engine::mutex_;
|
||||
#endif
|
||||
std::map<std::string,std::pair<int,std::string> > freetype_engine::name2file_;
|
||||
template void text_renderer<image_32>::render(double, double);
|
||||
template text_renderer<image_32>::text_renderer(image_32&, face_set_ptr, stroker&);
|
||||
template box2d<double>text_renderer<image_32>::prepare_glyphs(text_path*);
|
||||
|
||||
template void text_renderer<grid>::render_id(int, double, double, double);
|
||||
template text_renderer<grid>::text_renderer(grid&, face_set_ptr, stroker&);
|
||||
template box2d<double>text_renderer<grid>::prepare_glyphs(text_path*);
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ void grid_renderer<T>::process(shield_symbolizer const& sym,
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
|
||||
// TODO- clamp to at least 4 px otherwise interactivity is too small
|
||||
int w = (*marker)->width()/pixmap_.get_resolution();
|
||||
|
||||
@ -89,7 +89,7 @@ void grid_renderer<T>::process(text_symbolizer const& sym,
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
faces->get_string_info(info, text, 0);
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0; i<num_geom; ++i)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user