Refactor some of the font set stuff so that the cairo renderer can be
made to work again.
This commit is contained in:
parent
beaa2c33de
commit
026e4e71e7
4 changed files with 191 additions and 168 deletions
|
@ -59,6 +59,28 @@ extern "C"
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
class MAPNIK_DECL font_glyph : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
font_glyph(FT_Face face, unsigned index)
|
||||
: face_(face), index_(index) {}
|
||||
|
||||
FT_Face get_face() const
|
||||
{
|
||||
return face_;
|
||||
}
|
||||
|
||||
unsigned get_index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
private:
|
||||
FT_Face face_;
|
||||
unsigned index_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<font_glyph> glyph_ptr;
|
||||
|
||||
class font_face : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
@ -75,11 +97,6 @@ namespace mapnik
|
|||
return std::string(face_->style_name);
|
||||
}
|
||||
|
||||
unsigned num_glyphs() const
|
||||
{
|
||||
return face_->num_glyphs;
|
||||
}
|
||||
|
||||
FT_GlyphSlot glyph() const
|
||||
{
|
||||
return face_->glyph;
|
||||
|
@ -117,77 +134,37 @@ namespace mapnik
|
|||
};
|
||||
|
||||
typedef boost::shared_ptr<font_face> face_ptr;
|
||||
|
||||
class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>,
|
||||
// private boost::noncopyable
|
||||
|
||||
class MAPNIK_DECL font_face_set : private boost::noncopyable
|
||||
{
|
||||
// friend class mapnik::CreateStatic<freetype_engine>;
|
||||
public:
|
||||
static bool register_font(std::string const& file_name);
|
||||
static std::vector<std::string> face_names ();
|
||||
face_ptr create_face(std::string const& family_name);
|
||||
virtual ~freetype_engine();
|
||||
freetype_engine();
|
||||
private:
|
||||
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;
|
||||
itr = faces_.find(name);
|
||||
if (itr != faces_.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
face_ptr face = engine_.create_face(name);
|
||||
if (face)
|
||||
{
|
||||
faces_.insert(make_pair(name,face));
|
||||
}
|
||||
return face;
|
||||
}
|
||||
}
|
||||
private:
|
||||
faces faces_;
|
||||
font_engine_type & engine_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct text_renderer : private boost::noncopyable
|
||||
{
|
||||
typedef std::pair<unsigned,unsigned> dimension_t;
|
||||
|
||||
struct glyph_t : boost::noncopyable
|
||||
|
||||
font_face_set(void)
|
||||
: faces_() {}
|
||||
|
||||
void add(face_ptr face)
|
||||
{
|
||||
FT_Glyph image;
|
||||
glyph_t(FT_Glyph image_) : image(image_) {}
|
||||
~glyph_t () { FT_Done_Glyph(image);}
|
||||
};
|
||||
|
||||
typedef boost::ptr_vector<glyph_t> glyphs_t;
|
||||
typedef T pixmap_type;
|
||||
|
||||
text_renderer (pixmap_type & pixmap, std::vector<face_ptr> faces)
|
||||
: pixmap_(pixmap),
|
||||
faces_(faces),
|
||||
fill_(0,0,0),
|
||||
halo_fill_(255,255,255),
|
||||
halo_radius_(0) {}
|
||||
faces_.push_back(face);
|
||||
}
|
||||
|
||||
unsigned size() const
|
||||
{
|
||||
return faces_.size();
|
||||
}
|
||||
|
||||
glyph_ptr get_glyph(unsigned c) const
|
||||
{
|
||||
for (std::vector<face_ptr>::const_iterator face = faces_.begin(); face != faces_.end(); ++face)
|
||||
{
|
||||
FT_Face f = (*face)->get_face();
|
||||
FT_UInt g = (*face)->get_char(c);
|
||||
|
||||
if (g) return glyph_ptr(new font_glyph(f, g));
|
||||
}
|
||||
|
||||
return glyph_ptr();
|
||||
}
|
||||
|
||||
dimension_t character_dimensions(const unsigned c)
|
||||
{
|
||||
|
@ -200,31 +177,9 @@ namespace mapnik
|
|||
|
||||
FT_BBox glyph_bbox;
|
||||
FT_Glyph image;
|
||||
|
||||
FT_Face face = (*faces_.begin())->get_face();
|
||||
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, c);
|
||||
|
||||
// If there's no glyph_index we loop through the remaining fonts
|
||||
// in the fontset looking for one.
|
||||
if (!glyph_index) {
|
||||
std::vector<face_ptr>::iterator itr = faces_.begin();
|
||||
std::vector<face_ptr>::iterator end = faces_.end();
|
||||
|
||||
++itr; // Skip the first one, we already tried it.
|
||||
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
FT_Face f = (*itr)->get_face();
|
||||
|
||||
glyph_index = FT_Get_Char_Index(f, c);
|
||||
|
||||
if (glyph_index) {
|
||||
face = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
glyph_ptr glyph = get_glyph(c);
|
||||
FT_Face face = glyph->get_face();
|
||||
|
||||
matrix.xx = (FT_Fixed)( 1 * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)( 0 * 0x10000L );
|
||||
|
@ -233,7 +188,7 @@ namespace mapnik
|
|||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph (face, glyph_index, FT_LOAD_NO_HINTING);
|
||||
error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
return dimension_t(0, 0);
|
||||
|
||||
|
@ -327,14 +282,115 @@ namespace mapnik
|
|||
info.set_dimensions(width, height);
|
||||
}
|
||||
|
||||
void set_pixel_sizes(unsigned size)
|
||||
{
|
||||
for (std::vector<face_ptr>::iterator face = faces_.begin(); face != faces_.end(); ++face)
|
||||
{
|
||||
(*face)->set_pixel_sizes(size);
|
||||
}
|
||||
}
|
||||
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>,
|
||||
// private boost::noncopyable
|
||||
{
|
||||
// friend class mapnik::CreateStatic<freetype_engine>;
|
||||
public:
|
||||
static bool register_font(std::string const& file_name);
|
||||
static std::vector<std::string> face_names ();
|
||||
face_ptr create_face(std::string const& family_name);
|
||||
virtual ~freetype_engine();
|
||||
freetype_engine();
|
||||
private:
|
||||
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;
|
||||
itr = faces_.find(name);
|
||||
if (itr != faces_.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
face_ptr face = engine_.create_face(name);
|
||||
if (face)
|
||||
{
|
||||
faces_.insert(make_pair(name,face));
|
||||
}
|
||||
return face;
|
||||
}
|
||||
}
|
||||
|
||||
face_set_ptr get_face_set(std::string const& name)
|
||||
{
|
||||
face_set_ptr face_set(new font_face_set);
|
||||
if (face_ptr face = get_face(name))
|
||||
{
|
||||
face_set->add(face);
|
||||
}
|
||||
return face_set;
|
||||
}
|
||||
|
||||
face_set_ptr get_face_set(FontSet const& fontset)
|
||||
{
|
||||
std::vector<std::string> const& names = fontset.get_face_names();
|
||||
face_set_ptr face_set(new font_face_set);
|
||||
for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
|
||||
{
|
||||
if (face_ptr face = get_face(*name))
|
||||
{
|
||||
face_set->add(face);
|
||||
}
|
||||
}
|
||||
return face_set;
|
||||
}
|
||||
private:
|
||||
faces faces_;
|
||||
font_engine_type & engine_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct text_renderer : private boost::noncopyable
|
||||
{
|
||||
struct glyph_t : boost::noncopyable
|
||||
{
|
||||
FT_Glyph image;
|
||||
glyph_t(FT_Glyph image_) : image(image_) {}
|
||||
~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)
|
||||
: pixmap_(pixmap),
|
||||
faces_(faces),
|
||||
fill_(0,0,0),
|
||||
halo_fill_(255,255,255),
|
||||
halo_radius_(0) {}
|
||||
|
||||
void set_pixel_size(unsigned size)
|
||||
{
|
||||
std::vector<face_ptr>::iterator itr = faces_.begin();
|
||||
std::vector<face_ptr>::iterator end = faces_.end();
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
(*itr)->set_pixel_sizes(size);
|
||||
}
|
||||
faces_->set_pixel_sizes(size);
|
||||
}
|
||||
|
||||
void set_fill(mapnik::Color const& fill)
|
||||
|
@ -365,8 +421,6 @@ namespace mapnik
|
|||
bbox.xMin = bbox.yMin = 32000; // Initialize these so we can tell if we
|
||||
bbox.xMax = bbox.yMax = -32000; // properly grew the bbox later
|
||||
|
||||
std::vector<face_ptr>::iterator end = faces_.end();
|
||||
|
||||
for (int i = 0; i < path->num_nodes(); i++)
|
||||
{
|
||||
int c;
|
||||
|
@ -385,44 +439,9 @@ namespace mapnik
|
|||
|
||||
pen.x = int(x * 64);
|
||||
pen.y = int(y * 64);
|
||||
|
||||
FT_Face face = (*faces_.begin())->get_face();
|
||||
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, unsigned(c));
|
||||
|
||||
// If there's no glyph_index we loop through the remaining fonts
|
||||
// in the fontset looking for one.
|
||||
if (!glyph_index) {
|
||||
std::vector<face_ptr>::iterator itr = faces_.begin();
|
||||
++itr; // Skip the first one, we already tried it.
|
||||
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
// TODO Enable when we have support for setting verbosity
|
||||
//std::clog << "prepare_glyphs: Falling back to font named \""
|
||||
// << (*itr)->family_name() << " " << (*itr)->style_name()
|
||||
// << "\"" << std::endl;
|
||||
#endif
|
||||
|
||||
FT_Face f = (*itr)->get_face();
|
||||
|
||||
glyph_index = FT_Get_Char_Index(f, unsigned(c));
|
||||
|
||||
if (glyph_index) {
|
||||
face = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPNIK_DEBUG
|
||||
// TODO Enable when we have support for setting verbosity
|
||||
//if (!glyph_index) {
|
||||
// std::clog << "prepare_glyphs: Failed to fall back, glyph "
|
||||
// << c << " not found in any font." << std::endl;
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
|
||||
glyph_ptr glyph = faces_->get_glyph(unsigned(c));
|
||||
FT_Face face = glyph->get_face();
|
||||
|
||||
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
||||
|
@ -431,7 +450,7 @@ namespace mapnik
|
|||
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_HINTING);
|
||||
error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
|
||||
if ( error )
|
||||
continue;
|
||||
|
||||
|
@ -558,7 +577,7 @@ namespace mapnik
|
|||
}
|
||||
|
||||
pixmap_type & pixmap_;
|
||||
std::vector<face_ptr> faces_;
|
||||
face_set_ptr faces_;
|
||||
mapnik::Color fill_;
|
||||
mapnik::Color halo_fill_;
|
||||
int halo_radius_;
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace mapnik
|
|||
FontSet(std::string const& name);
|
||||
FontSet(FontSet const& rhs);
|
||||
FontSet& operator=(FontSet const& rhs);
|
||||
unsigned size() const;
|
||||
std::string const& get_name() const;
|
||||
void add_face_name(std::string);
|
||||
std::vector<std::string> const& get_face_names() const;
|
||||
|
|
|
@ -459,11 +459,18 @@ namespace mapnik
|
|||
boost::shared_ptr<ImageData32> const& data = sym.get_image();
|
||||
if (text.length() > 0 && data)
|
||||
{
|
||||
std::vector<face_ptr> faces;
|
||||
|
||||
faces.push_back(font_manager_.get_face(sym.get_face_name()));
|
||||
|
||||
if (faces.size() > 0)
|
||||
face_set_ptr faces;
|
||||
|
||||
if (sym.get_fontset().size() > 0)
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
||||
if (faces->size() > 0)
|
||||
{
|
||||
text_renderer<mapnik::Image32> ren(pixmap_, faces);
|
||||
|
||||
|
@ -472,7 +479,7 @@ namespace mapnik
|
|||
|
||||
string_info info(text);
|
||||
|
||||
ren.get_string_info(info);
|
||||
faces->get_string_info(info);
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
|
@ -675,27 +682,18 @@ namespace mapnik
|
|||
{
|
||||
Color const& fill = sym.get_fill();
|
||||
|
||||
std::vector<face_ptr> faces;
|
||||
|
||||
FontSet fontset = sym.get_fontset();
|
||||
std::vector<std::string> face_names = fontset.get_face_names();
|
||||
|
||||
if (face_names.size() > 0)
|
||||
{
|
||||
std::vector<std::string>::iterator itr = face_names.begin();
|
||||
std::vector<std::string>::iterator end = face_names.end();
|
||||
face_set_ptr faces;
|
||||
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
faces.push_back(font_manager_.get_face(*itr));
|
||||
}
|
||||
if (sym.get_fontset().size() > 0)
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
{
|
||||
faces.push_back(font_manager_.get_face(sym.get_face_name()));
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
||||
if (faces.size() > 0)
|
||||
|
||||
if (faces->size() > 0)
|
||||
{
|
||||
text_renderer<mapnik::Image32> ren(pixmap_, faces);
|
||||
ren.set_pixel_size(sym.get_text_size());
|
||||
|
@ -707,7 +705,7 @@ namespace mapnik
|
|||
|
||||
string_info info(text);
|
||||
|
||||
ren.get_string_info(info);
|
||||
faces->get_string_info(info);
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0;i<num_geom;++i)
|
||||
{
|
||||
|
|
|
@ -52,6 +52,11 @@ namespace mapnik
|
|||
|
||||
FontSet::~FontSet() {}
|
||||
|
||||
unsigned FontSet::size() const
|
||||
{
|
||||
return face_names_.size();
|
||||
}
|
||||
|
||||
void FontSet::add_face_name(std::string face_name)
|
||||
{
|
||||
face_names_.push_back(face_name);
|
||||
|
|
Loading…
Add table
Reference in a new issue