Use UTF16 directly to avoid reencoding and allow easy mapping of chars to glyphs.
This commit is contained in:
parent
89b727d2fc
commit
91d80dc7c1
3 changed files with 16 additions and 17 deletions
|
@ -14,7 +14,7 @@ namespace mapnik
|
||||||
struct glyph_info
|
struct glyph_info
|
||||||
{
|
{
|
||||||
font_glyph glyph;
|
font_glyph glyph;
|
||||||
uint32_t byte_position;
|
uint32_t char_index; //Position in the string of all characters i.e. before itemizing
|
||||||
uint32_t x_advance;
|
uint32_t x_advance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,18 +21,17 @@ void text_layout::break_lines()
|
||||||
void text_layout::shape_text()
|
void text_layout::shape_text()
|
||||||
{
|
{
|
||||||
glyphs_.reserve(itemizer.get_text().length()); //Preallocate memory
|
glyphs_.reserve(itemizer.get_text().length()); //Preallocate memory
|
||||||
uint32_t byte_offset = 0;
|
uint32_t offset = 0; //in utf16 code points
|
||||||
std::list<text_item> const& list = itemizer.itemize();
|
std::list<text_item> const& list = itemizer.itemize();
|
||||||
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++)
|
||||||
{
|
{
|
||||||
face_set_ptr face_set = font_manager_.get_face_set(itr->format.face_name, itr->format.fontset);
|
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_set->set_character_sizes(itr->format.text_size);
|
||||||
face_ptr face = *(face_set->begin()); //TODO: Implement font sets correctly
|
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
|
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, itr->rtl == UBIDI_DEFAULT_RTL, itr->script);
|
uint32_t chars = shaper.process_text(itr->str, itr->rtl == UBIDI_DEFAULT_RTL, itr->script);
|
||||||
hb_buffer_t *buffer = shaper.get_buffer();
|
hb_buffer_t *buffer = shaper.get_buffer();
|
||||||
|
|
||||||
unsigned num_glyphs = hb_buffer_get_length(buffer);
|
unsigned num_glyphs = hb_buffer_get_length(buffer);
|
||||||
|
@ -41,27 +40,27 @@ void text_layout::shape_text()
|
||||||
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, NULL);
|
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, NULL);
|
||||||
|
|
||||||
std::string s;
|
std::string s;
|
||||||
std::cout << "Processing item '" << itr->str.toUTF8String(s) << "' (" << uscript_getName(itr->script) << "," << itr->str.length() << "," << num_glyphs << ")\n";
|
std::cout << "Processing item '" << itr->str.toUTF8String(s) << "' (" << uscript_getName(itr->script) << "," << itr->str.length() << "," << num_glyphs << "," << itr->rtl << ")\n";
|
||||||
|
|
||||||
for (unsigned i=0; i<num_glyphs; i++)
|
for (unsigned i=0; i<num_glyphs; i++)
|
||||||
{
|
{
|
||||||
glyph_info tmp;
|
glyph_info tmp;
|
||||||
tmp.byte_position = byte_offset + glyphs[i].cluster;
|
tmp.char_index = offset + glyphs[i].cluster;
|
||||||
tmp.glyph.index = glyphs[i].codepoint;
|
tmp.glyph.index = glyphs[i].codepoint;
|
||||||
//TODO: tmp.glyph.set_face();
|
tmp.glyph.face = face;
|
||||||
tmp.x_advance = positions[i].x_advance;
|
tmp.x_advance = positions[i].x_advance;
|
||||||
glyphs_.push_back(tmp);
|
glyphs_.push_back(tmp);
|
||||||
}
|
}
|
||||||
byte_offset += bytes;
|
offset += chars;
|
||||||
}
|
}
|
||||||
std::string s;
|
std::cout << "text_length: unicode chars: " << itemizer.get_text().length() << " glyphs: " << glyphs_.size() << "\n";
|
||||||
std::cout << "text_length: unicode chars: " << itemizer.get_text().length() << " bytes: " <<itemizer.get_text().toUTF8String(s).length() << " glyphs: " << glyphs_.size() << "\n";
|
|
||||||
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->glyph.index <<
|
std::cout << "'" << (char) itemizer.get_text().charAt(itr2->char_index) <<
|
||||||
" cluster: " << itr2->byte_position <<
|
"' glyph codepoint:" << itr2->glyph.index <<
|
||||||
" x_advance: "<< itr2->x_advance << "\n";
|
" cluster: " << itr2->char_index <<
|
||||||
|
" x_advance: "<< itr2->x_advance/64.0 << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,16 @@ uint32_t text_shaping::process_text(UnicodeString const& text, bool rtl, UScript
|
||||||
if (!font_) return 0;
|
if (!font_) return 0;
|
||||||
hb_buffer_reset(buffer_);
|
hb_buffer_reset(buffer_);
|
||||||
|
|
||||||
std::string s;
|
uint32_t length = text.length();
|
||||||
text.toUTF8String(s);
|
|
||||||
hb_buffer_add_utf8(buffer_, s.c_str(), s.length(), 0, -1);
|
hb_buffer_add_utf16(buffer_, text.getBuffer(), length, 0, -1);
|
||||||
hb_buffer_set_direction(buffer_, rtl?HB_DIRECTION_RTL:HB_DIRECTION_LTR);
|
hb_buffer_set_direction(buffer_, rtl?HB_DIRECTION_RTL:HB_DIRECTION_LTR);
|
||||||
hb_buffer_set_script(buffer_, hb_icu_script_to_script(script));
|
hb_buffer_set_script(buffer_, hb_icu_script_to_script(script));
|
||||||
#if 0
|
#if 0
|
||||||
hb_buffer_set_language(buffer, hb_language_from_string (language, -1));
|
hb_buffer_set_language(buffer, hb_language_from_string (language, -1));
|
||||||
#endif
|
#endif
|
||||||
hb_shape(font_, buffer_, 0 /*features*/, 0 /*num_features*/);
|
hb_shape(font_, buffer_, 0 /*features*/, 0 /*num_features*/);
|
||||||
return s.length();
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_shaping::free_data(void *data)
|
void text_shaping::free_data(void *data)
|
||||||
|
|
Loading…
Add table
Reference in a new issue