Prepare for making HarfBuzz an optional dependency.

This commit is contained in:
Hermann Kraus 2012-09-23 03:19:47 +02:00
parent 7439eaed67
commit 748cf62de3
3 changed files with 86 additions and 75 deletions

View file

@ -180,6 +180,7 @@ source = Split(
text/placements/simple.cpp
text/shaping.cpp
text/layout.cpp
text/layout_shape_hb.cpp
text/itemizer.cpp
text/scrptrun.cpp
text/face.cpp

View file

@ -20,14 +20,8 @@
*
*****************************************************************************/
#include <mapnik/text/layout.hpp>
#include <mapnik/text/shaping.hpp>
#include <mapnik/text/text_properties.hpp>
//stl
#include <iostream>
// harf-buzz
#include <harfbuzz/hb.h>
#include <mapnik/debug.hpp>
// ICU
#include <unicode/brkiter.h>
@ -130,73 +124,6 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
}
}
void text_layout::shape_text(text_line_ptr line)
{
unsigned start = line->get_first_char();
unsigned end = line->get_last_char();
UnicodeString const& text = itemizer_.get_text();
size_t length = end - start;
line->reserve(length); //Preallocate memory
std::list<text_item> const& list = itemizer_.itemize(start, end);
std::list<text_item>::const_iterator itr = list.begin(), list_end = list.end();
for (; itr != list_end; itr++)
{
face_set_ptr face_set = font_manager_.get_face_set(itr->format->face_name, itr->format->fontset);
face_set->set_character_sizes(itr->format->text_size);
font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end();
for (; face_itr != face_end; face_itr++)
{
face_ptr face = *face_itr;
text_shaping shaper(face->get_face()); //TODO: Make this more efficient by caching this object in font_face
shaper.process_text(text, itr->start, itr->end, itr->rtl == UBIDI_RTL, itr->script);
hb_buffer_t *buffer = shaper.get_buffer();
unsigned num_glyphs = hb_buffer_get_length(buffer);
hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer, NULL);
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, NULL);
bool font_has_all_glyphs = true;
/* Check if all glyphs are valid. */
for (unsigned i=0; i<num_glyphs; i++)
{
if (!glyphs[i].codepoint)
{
font_has_all_glyphs = false;
break;
}
}
if (!font_has_all_glyphs)
{
//Try next font in fontset
continue;
}
for (unsigned i=0; i<num_glyphs; i++)
{
glyph_info tmp;
tmp.char_index = glyphs[i].cluster;
tmp.glyph_index = glyphs[i].codepoint;
tmp.width = positions[i].x_advance / 64.0;
tmp.offset.set(positions[i].x_offset / 64.0, positions[i].y_offset / 64.0);
tmp.face = face;
tmp.format = itr->format;
face->glyph_dimensions(tmp);
width_map_[glyphs[i].cluster] += tmp.width;
line->add_glyph(tmp);
}
line->update_max_char_height(face->get_char_height());
break; //When we reach this point the current font had all glyphs.
}
}
}
void text_layout::add_line(text_line_ptr line)
{
if (lines_.empty())
@ -320,7 +247,7 @@ unsigned text_line::get_last_char() const
unsigned text_line::size() const
{
glyphs_.size();
return glyphs_.size();
}
} //ns mapnik

View file

@ -0,0 +1,83 @@
//mapnik
#include <mapnik/text/layout.hpp>
#include <mapnik/text/shaping.hpp>
#include <mapnik/text/text_properties.hpp>
//stl
#include <list>
// harf-buzz
#include <harfbuzz/hb.h>
namespace mapnik
{
void text_layout::shape_text(text_line_ptr line)
{
unsigned start = line->get_first_char();
unsigned end = line->get_last_char();
UnicodeString const& text = itemizer_.get_text();
size_t length = end - start;
line->reserve(length); //Preallocate memory
std::list<text_item> const& list = itemizer_.itemize(start, end);
std::list<text_item>::const_iterator itr = list.begin(), list_end = list.end();
for (; itr != list_end; itr++)
{
face_set_ptr face_set = font_manager_.get_face_set(itr->format->face_name, itr->format->fontset);
face_set->set_character_sizes(itr->format->text_size);
font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end();
for (; face_itr != face_end; face_itr++)
{
face_ptr face = *face_itr;
text_shaping shaper(face->get_face()); //TODO: Make this more efficient by caching this object in font_face
shaper.process_text(text, itr->start, itr->end, itr->rtl == UBIDI_RTL, itr->script);
hb_buffer_t *buffer = shaper.get_buffer();
unsigned num_glyphs = hb_buffer_get_length(buffer);
hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer, NULL);
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, NULL);
bool font_has_all_glyphs = true;
/* Check if all glyphs are valid. */
for (unsigned i=0; i<num_glyphs; i++)
{
if (!glyphs[i].codepoint)
{
font_has_all_glyphs = false;
break;
}
}
if (!font_has_all_glyphs)
{
//Try next font in fontset
continue;
}
for (unsigned i=0; i<num_glyphs; i++)
{
glyph_info tmp;
tmp.char_index = glyphs[i].cluster;
tmp.glyph_index = glyphs[i].codepoint;
tmp.width = positions[i].x_advance / 64.0;
tmp.offset.set(positions[i].x_offset / 64.0, positions[i].y_offset / 64.0);
tmp.face = face;
tmp.format = itr->format;
face->glyph_dimensions(tmp);
width_map_[glyphs[i].cluster] += tmp.width;
line->add_glyph(tmp);
}
line->update_max_char_height(face->get_char_height());
break; //When we reach this point the current font had all glyphs.
}
}
}
} //ns mapnik