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;
class MAPNIK_DECL font_glyph : private boost::noncopyable
class MAPNIK_DECL font_glyph
{
public:
font_glyph() : face(), index(0) {}
font_glyph(face_ptr face, unsigned index)
: face_(face), index_(index) {}
: face(face), index(index) {}
face_ptr get_face() const
{
return face_;
return face;
}
unsigned get_index() const
{
return index_;
return index;
}
private:
face_ptr face_;
unsigned index_;
face_ptr face;
unsigned index;
};
typedef boost::shared_ptr<font_glyph> glyph_ptr;
@ -152,6 +153,7 @@ private:
class MAPNIK_DECL font_face_set : private boost::noncopyable
{
public:
typedef std::vector<face_ptr>::iterator iterator;
font_face_set(void)
: faces_(),
dimension_cache_() {}
@ -179,6 +181,16 @@ public:
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);
void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

View file

@ -56,28 +56,7 @@ public:
CoordTransform const& t,
FaceManagerT &font_manager,
DetectorT &detector,
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();
}
box2d<double> const& query_extent);
/** Return next placement.
* If no more placements are found false is returned.
@ -142,13 +121,7 @@ public:
CoordTransform const &t,
FaceManagerT &font_manager,
DetectorT &detector,
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& query_extent);
box2d<double> const& get_marker_extent() const
{

View file

@ -3,6 +3,7 @@
//mapnik
#include <mapnik/text/itemizer.hpp>
#include <mapnik/font_engine_freetype.hpp>
//stl
#include <vector>
@ -12,7 +13,7 @@ namespace mapnik
struct glyph_info
{
uint32_t codepoint;
font_glyph glyph;
uint32_t byte_position;
uint32_t x_advance;
};
@ -20,7 +21,7 @@ struct glyph_info
class text_layout
{
public:
text_layout();
text_layout(face_manager_freetype & font_manager);
inline void add_text(UnicodeString const& str, char_properties const& format)
{
itemizer.add_text(str, format);
@ -33,6 +34,7 @@ public:
private:
text_itemizer itemizer;
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_glyph_info_t;
// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
}
namespace mapnik
{
@ -14,7 +21,7 @@ class text_shaping
{
public:
//TODO: Get font file from font name
text_shaping();
text_shaping(FT_Face face);
~text_shaping();
uint32_t process_text(UnicodeString const& text);
@ -27,6 +34,7 @@ protected:
hb_font_t *font_;
hb_buffer_t *buffer_;
FT_Face face_;
};
} //ns mapnik

View file

@ -29,6 +29,30 @@
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>
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next()
{
@ -96,6 +120,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
point_itr_ = points_.begin();
continue; //Reexecute size check
}
return false; //TODO
finder_->clear_placements();
finder_->find_point_placement(point_itr_->first, point_itr_->second, angle_);
if (!finder_->get_results().empty())
@ -227,6 +252,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
return false;
}
placement_->properties.process(layout_, feature_);
layout_.shape_text();
//TODO
// info_ = &(text_.get_string_info());
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>
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 shield_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
} //namespace

View file

@ -9,7 +9,8 @@
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();
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);
hb_buffer_t *buffer = shaper.get_buffer();
@ -41,7 +47,8 @@ void text_layout::shape_text()
{
glyph_info tmp;
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;
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();
for (;itr2 != end2; itr2++)
{
std::cout << "glyph codepoint:" << itr2->codepoint <<
std::cout << "glyph codepoint:" << itr2->glyph.index <<
" cluster: " << itr2->byte_position <<
" 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),
buffer_ (hb_buffer_create())
buffer_ (hb_buffer_create()),
face_(face)
{
load_font();
}
@ -53,38 +54,8 @@ void text_shaping::free_data(void *data)
void text_shaping::load_font()
{
//TODO: hb_ft_font_create
if (font_) return;
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_);
font_ = hb_ft_font_create(face_, NULL);
}
}