Use mapnik's face_manager instead of loading the font on our own.

This commit is contained in:
Hermann Kraus 2012-06-30 17:09:14 +02:00
parent 63e8b6d6db
commit 2e50936b13
7 changed files with 87 additions and 76 deletions

View file

@ -71,24 +71,25 @@ class string_info;
typedef boost::shared_ptr<font_face> face_ptr; typedef boost::shared_ptr<font_face> face_ptr;
class MAPNIK_DECL font_glyph : private boost::noncopyable class MAPNIK_DECL font_glyph
{ {
public: public:
font_glyph() : face(), index(0) {}
font_glyph(face_ptr face, unsigned index) font_glyph(face_ptr face, unsigned index)
: face_(face), index_(index) {} : face(face), index(index) {}
face_ptr get_face() const face_ptr get_face() const
{ {
return face_; return face;
} }
unsigned get_index() const unsigned get_index() const
{ {
return index_; return index;
} }
private: face_ptr face;
face_ptr face_; unsigned index;
unsigned index_;
}; };
typedef boost::shared_ptr<font_glyph> glyph_ptr; typedef boost::shared_ptr<font_glyph> glyph_ptr;
@ -152,6 +153,7 @@ private:
class MAPNIK_DECL font_face_set : private boost::noncopyable class MAPNIK_DECL font_face_set : private boost::noncopyable
{ {
public: public:
typedef std::vector<face_ptr>::iterator iterator;
font_face_set(void) font_face_set(void)
: faces_(), : faces_(),
dimension_cache_() {} dimension_cache_() {}
@ -179,6 +181,16 @@ public:
return boost::make_shared<font_glyph>(*faces_.begin(), 0); return boost::make_shared<font_glyph>(*faces_.begin(), 0);
} }
iterator begin()
{
return faces_.begin();
}
iterator end()
{
return faces_.end();
}
char_info character_dimensions(const unsigned c); char_info character_dimensions(const unsigned c);
void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format); void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

View file

@ -56,28 +56,7 @@ public:
CoordTransform const& t, CoordTransform const& t,
FaceManagerT &font_manager, FaceManagerT &font_manager,
DetectorT &detector, DetectorT &detector,
box2d<double> const& query_extent) box2d<double> const& query_extent);
: sym_(sym),
feature_(feature),
prj_trans_(prj_trans),
t_(t),
font_manager_(font_manager),
detector_(detector),
writer_(sym.get_metawriter()),
dims_(0, 0, width, height),
query_extent_(query_extent),
layout_(),
angle_(0.0),
placement_valid_(false),
points_on_line_(false),
finder_()
{
initialize_geometries();
if (!geometries_to_process_.size()) return;
placement_ = sym_.get_placement_options()->get_placement_info(scale_factor);
next_placement();
initialize_points();
}
/** Return next placement. /** Return next placement.
* If no more placements are found false is returned. * If no more placements are found false is returned.
@ -142,13 +121,7 @@ public:
CoordTransform const &t, CoordTransform const &t,
FaceManagerT &font_manager, FaceManagerT &font_manager,
DetectorT &detector, DetectorT &detector,
box2d<double> const& query_extent) : box2d<double> const& query_extent);
text_symbolizer_helper<FaceManagerT, DetectorT>(sym, feature, prj_trans, width, height, scale_factor, t, font_manager, detector, query_extent),
sym_(sym)
{
this->points_on_line_ = true;
init_marker();
}
box2d<double> const& get_marker_extent() const box2d<double> const& get_marker_extent() const
{ {

View file

@ -3,6 +3,7 @@
//mapnik //mapnik
#include <mapnik/text/itemizer.hpp> #include <mapnik/text/itemizer.hpp>
#include <mapnik/font_engine_freetype.hpp>
//stl //stl
#include <vector> #include <vector>
@ -12,7 +13,7 @@ namespace mapnik
struct glyph_info struct glyph_info
{ {
uint32_t codepoint; font_glyph glyph;
uint32_t byte_position; uint32_t byte_position;
uint32_t x_advance; uint32_t x_advance;
}; };
@ -20,7 +21,7 @@ struct glyph_info
class text_layout class text_layout
{ {
public: public:
text_layout(); text_layout(face_manager_freetype & font_manager);
inline void add_text(UnicodeString const& str, char_properties const& format) inline void add_text(UnicodeString const& str, char_properties const& format)
{ {
itemizer.add_text(str, format); itemizer.add_text(str, format);
@ -33,6 +34,7 @@ public:
private: private:
text_itemizer itemizer; text_itemizer itemizer;
std::vector<glyph_info> glyphs_; std::vector<glyph_info> glyphs_;
face_manager_freetype &font_manager_;
}; };
} }

View file

@ -7,6 +7,13 @@ class hb_font_t;
class hb_buffer_t; class hb_buffer_t;
class hb_glyph_info_t; class hb_glyph_info_t;
// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
}
namespace mapnik namespace mapnik
{ {
@ -14,7 +21,7 @@ class text_shaping
{ {
public: public:
//TODO: Get font file from font name //TODO: Get font file from font name
text_shaping(); text_shaping(FT_Face face);
~text_shaping(); ~text_shaping();
uint32_t process_text(UnicodeString const& text); uint32_t process_text(UnicodeString const& text);
@ -27,6 +34,7 @@ protected:
hb_font_t *font_; hb_font_t *font_;
hb_buffer_t *buffer_; hb_buffer_t *buffer_;
FT_Face face_;
}; };
} //ns mapnik } //ns mapnik

View file

@ -29,6 +29,30 @@
namespace mapnik { namespace mapnik {
template <typename FaceManagerT, typename DetectorT>
text_symbolizer_helper<FaceManagerT, DetectorT>::text_symbolizer_helper(const text_symbolizer &sym, const Feature &feature, const proj_transform &prj_trans, unsigned width, unsigned height, double scale_factor, const CoordTransform &t, FaceManagerT &font_manager, DetectorT &detector, const box2d<double> &query_extent)
: sym_(sym),
feature_(feature),
prj_trans_(prj_trans),
t_(t),
font_manager_(font_manager),
detector_(detector),
writer_(sym.get_metawriter()),
dims_(0, 0, width, height),
query_extent_(query_extent),
layout_(font_manager),
angle_(0.0),
placement_valid_(false),
points_on_line_(false),
finder_()
{
initialize_geometries();
if (!geometries_to_process_.size()) return;
placement_ = sym_.get_placement_options()->get_placement_info(scale_factor);
next_placement();
initialize_points();
}
template <typename FaceManagerT, typename DetectorT> template <typename FaceManagerT, typename DetectorT>
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next() bool text_symbolizer_helper<FaceManagerT, DetectorT>::next()
{ {
@ -96,6 +120,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
point_itr_ = points_.begin(); point_itr_ = points_.begin();
continue; //Reexecute size check continue; //Reexecute size check
} }
return false; //TODO
finder_->clear_placements(); finder_->clear_placements();
finder_->find_point_placement(point_itr_->first, point_itr_->second, angle_); finder_->find_point_placement(point_itr_->first, point_itr_->second, angle_);
if (!finder_->get_results().empty()) if (!finder_->get_results().empty())
@ -227,6 +252,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
return false; return false;
} }
placement_->properties.process(layout_, feature_); placement_->properties.process(layout_, feature_);
layout_.shape_text();
//TODO //TODO
// info_ = &(text_.get_string_info()); // info_ = &(text_.get_string_info());
if (placement_->properties.orientation) if (placement_->properties.orientation)
@ -257,6 +283,17 @@ placements_type &text_symbolizer_helper<FaceManagerT, DetectorT>::placements() c
/*****************************************************************************/ /*****************************************************************************/
template <typename FaceManagerT, typename DetectorT>
shield_symbolizer_helper<FaceManagerT, DetectorT>::shield_symbolizer_helper(const shield_symbolizer &sym, const Feature &feature, const proj_transform &prj_trans, unsigned width, unsigned height, double scale_factor, const CoordTransform &t, FaceManagerT &font_manager, DetectorT &detector, const box2d<double> &query_extent)
: text_symbolizer_helper<FaceManagerT, DetectorT>(
sym, feature, prj_trans, width, height,
scale_factor, t, font_manager, detector, query_extent),
sym_(sym)
{
this->points_on_line_ = true;
init_marker();
}
template <typename FaceManagerT, typename DetectorT> template <typename FaceManagerT, typename DetectorT>
bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next() bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next()
{ {
@ -417,4 +454,5 @@ agg::trans_affine const& shield_symbolizer_helper<FaceManagerT, DetectorT>::get_
template class text_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>; template class text_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
template class shield_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>; template class shield_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
} //namespace } //namespace

View file

@ -9,7 +9,8 @@
namespace mapnik namespace mapnik
{ {
text_layout::text_layout() text_layout::text_layout(face_manager_freetype &font_manager)
: font_manager_(font_manager)
{ {
} }
@ -25,7 +26,12 @@ void text_layout::shape_text()
std::list<text_item>::const_iterator itr = list.begin(), end = list.end(); std::list<text_item>::const_iterator itr = list.begin(), end = list.end();
for (;itr!=end; itr++) for (;itr!=end; itr++)
{ {
text_shaping shaper; face_set_ptr face_set = font_manager_.get_face_set(itr->format.face_name, itr->format.fontset);
//TODO: Difference pixel_sizes, char_sizes
face_set->set_character_sizes(itr->format.text_size);
face_ptr face = *(face_set->begin()); //TODO: Implement font sets correctly
text_shaping shaper(face->get_face()); //TODO: Make this more efficient by caching this object in font_face
uint32_t bytes = shaper.process_text(itr->str); uint32_t bytes = shaper.process_text(itr->str);
hb_buffer_t *buffer = shaper.get_buffer(); hb_buffer_t *buffer = shaper.get_buffer();
@ -41,7 +47,8 @@ void text_layout::shape_text()
{ {
glyph_info tmp; glyph_info tmp;
tmp.byte_position = byte_offset + glyphs[i].cluster; tmp.byte_position = byte_offset + glyphs[i].cluster;
tmp.codepoint = glyphs[i].codepoint; tmp.glyph.index = glyphs[i].codepoint;
//TODO: tmp.glyph.set_face();
tmp.x_advance = positions[i].x_advance; tmp.x_advance = positions[i].x_advance;
glyphs_.push_back(tmp); glyphs_.push_back(tmp);
} }
@ -52,7 +59,7 @@ void text_layout::shape_text()
std::vector<glyph_info>::const_iterator itr2 = glyphs_.begin(), end2 = glyphs_.end(); std::vector<glyph_info>::const_iterator itr2 = glyphs_.begin(), end2 = glyphs_.end();
for (;itr2 != end2; itr2++) for (;itr2 != end2; itr2++)
{ {
std::cout << "glyph codepoint:" << itr2->codepoint << std::cout << "glyph codepoint:" << itr2->glyph.index <<
" cluster: " << itr2->byte_position << " cluster: " << itr2->byte_position <<
" x_advance: "<< itr2->x_advance << "\n"; " x_advance: "<< itr2->x_advance << "\n";
} }

View file

@ -15,9 +15,10 @@ namespace mapnik
{ {
text_shaping::text_shaping() text_shaping::text_shaping(FT_Face face)
: font_(0), : font_(0),
buffer_ (hb_buffer_create()) buffer_ (hb_buffer_create()),
face_(face)
{ {
load_font(); load_font();
} }
@ -53,38 +54,8 @@ void text_shaping::free_data(void *data)
void text_shaping::load_font() void text_shaping::load_font()
{ {
//TODO: hb_ft_font_create
if (font_) return; if (font_) return;
font_ = hb_ft_font_create(face_, NULL);
char *font_data;
unsigned int size;
// std::ifstream file("./unifont-5.1.20080907.ttf" /*TODO*/, std::ios::in|std::ios::binary|std::ios::ate);
std::ifstream file("./DejaVuSans.ttf" /*TODO*/, std::ios::in|std::ios::binary|std::ios::ate);
if (file.is_open())
{
size = file.tellg();
font_data = new char[size];
file.seekg(0, std::ios::beg);
file.read(font_data, size);
file.close();
} else {
std::cerr << "Could not open font!\n";
return ;//TODO: Raise exception
}
hb_blob_t *blob = hb_blob_create(font_data, size, HB_MEMORY_MODE_WRITABLE, font_data, &free_data);
hb_face_t *face = hb_face_create(blob, 0 /*face_index*/);
hb_blob_destroy(blob);
font_ = hb_font_create(face);
#if 1
//TODO: Font size
unsigned int upem = hb_face_get_upem(face);
hb_font_set_scale(font_, upem, upem);
#endif
hb_face_destroy(face);
hb_ft_font_set_funcs(font_);
} }
} }