Move font engine functions from .hpp to .cpp.

This commit is contained in:
Hermann Kraus 2012-01-21 01:47:02 +01:00
parent 34405a5d9e
commit 5fd7035527
7 changed files with 224 additions and 211 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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