Merge branch 'issue-3050' of https://github.com/wmde/mapnik into wmde-issue-3050
This commit is contained in:
commit
5370dac598
1 changed files with 39 additions and 10 deletions
|
@ -93,6 +93,19 @@ static void shape_text(text_line & line,
|
||||||
std::size_t pos = 0;
|
std::size_t pos = 0;
|
||||||
font_feature_settings const& ff_settings = text_item.format_->ff_settings;
|
font_feature_settings const& ff_settings = text_item.format_->ff_settings;
|
||||||
int ff_count = safe_cast<int>(ff_settings.count());
|
int ff_count = safe_cast<int>(ff_settings.count());
|
||||||
|
|
||||||
|
// rendering information for a single glyph
|
||||||
|
struct glyph_face_info
|
||||||
|
{
|
||||||
|
face_ptr face;
|
||||||
|
hb_glyph_info_t glyph;
|
||||||
|
hb_glyph_position_t position;
|
||||||
|
};
|
||||||
|
// this table is filled with information for rendering each glyph, so that
|
||||||
|
// several font faces can be used in a single text_item
|
||||||
|
std::vector<glyph_face_info> glyphinfos;
|
||||||
|
unsigned valid_glyphs = 0;
|
||||||
|
|
||||||
for (auto const& face : *face_set)
|
for (auto const& face : *face_set)
|
||||||
{
|
{
|
||||||
++pos;
|
++pos;
|
||||||
|
@ -112,20 +125,29 @@ static void shape_text(text_line & line,
|
||||||
|
|
||||||
unsigned num_glyphs = hb_buffer_get_length(buffer.get());
|
unsigned num_glyphs = hb_buffer_get_length(buffer.get());
|
||||||
|
|
||||||
|
// if the number of rendered glyphs has increased, we need to resize the table
|
||||||
|
if (num_glyphs > glyphinfos.size())
|
||||||
|
{
|
||||||
|
glyphinfos.resize(num_glyphs);
|
||||||
|
}
|
||||||
|
|
||||||
hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer.get(), nullptr);
|
hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer.get(), nullptr);
|
||||||
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr);
|
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr);
|
||||||
|
|
||||||
bool font_has_all_glyphs = true;
|
|
||||||
// Check if all glyphs are valid.
|
// Check if all glyphs are valid.
|
||||||
for (unsigned i=0; i<num_glyphs; ++i)
|
for (unsigned i=0; i<num_glyphs; ++i)
|
||||||
{
|
{
|
||||||
if (!glyphs[i].codepoint)
|
// if we have a valid codepoint, save rendering info.
|
||||||
|
if (glyphs[i].codepoint)
|
||||||
{
|
{
|
||||||
font_has_all_glyphs = false;
|
if (!glyphinfos[i].glyph.codepoint)
|
||||||
break;
|
{
|
||||||
|
++valid_glyphs;
|
||||||
|
}
|
||||||
|
glyphinfos[i] = { face, glyphs[i], positions[i] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!font_has_all_glyphs && (pos < num_faces))
|
if (valid_glyphs < num_glyphs && (pos < num_faces))
|
||||||
{
|
{
|
||||||
//Try next font in fontset
|
//Try next font in fontset
|
||||||
continue;
|
continue;
|
||||||
|
@ -134,14 +156,21 @@ static void shape_text(text_line & line,
|
||||||
double max_glyph_height = 0;
|
double max_glyph_height = 0;
|
||||||
for (unsigned i=0; i<num_glyphs; ++i)
|
for (unsigned i=0; i<num_glyphs; ++i)
|
||||||
{
|
{
|
||||||
auto const& gpos = positions[i];
|
auto& gpos = positions[i];
|
||||||
auto const& glyph = glyphs[i];
|
auto& glyph = glyphs[i];
|
||||||
|
face_ptr theface = face;
|
||||||
|
if (glyphinfos[i].glyph.codepoint)
|
||||||
|
{
|
||||||
|
gpos = glyphinfos[i].position;
|
||||||
|
glyph = glyphinfos[i].glyph;
|
||||||
|
theface = glyphinfos[i].face;
|
||||||
|
}
|
||||||
unsigned char_index = glyph.cluster;
|
unsigned char_index = glyph.cluster;
|
||||||
glyph_info g(glyph.codepoint,char_index,text_item.format_);
|
glyph_info g(glyph.codepoint,char_index,text_item.format_);
|
||||||
if (face->glyph_dimensions(g))
|
if (theface->glyph_dimensions(g))
|
||||||
{
|
{
|
||||||
g.face = face;
|
g.face = theface;
|
||||||
g.scale_multiplier = size / face->get_face()->units_per_EM;
|
g.scale_multiplier = size / theface->get_face()->units_per_EM;
|
||||||
//Overwrite default advance with better value provided by HarfBuzz
|
//Overwrite default advance with better value provided by HarfBuzz
|
||||||
g.unscaled_advance = gpos.x_advance;
|
g.unscaled_advance = gpos.x_advance;
|
||||||
g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier);
|
g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier);
|
||||||
|
|
Loading…
Reference in a new issue