From 755d178d20ec12b8afe8bcac87f77a7fe0356c3a Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 31 Jan 2017 17:44:25 +0100 Subject: [PATCH] alternative exaustive face fallback implementation ref #3534 #3559 --- include/mapnik/text/harfbuzz_shaper.hpp | 81 +++++++++++-------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 56887e5fc..e4672526f 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -80,17 +80,17 @@ static void shape_text(text_line & line, line.reserve(length); auto hb_buffer_deleter = [](hb_buffer_t * buffer) { hb_buffer_destroy(buffer);}; - const std::unique_ptr buffer(hb_buffer_create(),hb_buffer_deleter); + const std::unique_ptr buffer(hb_buffer_create(), hb_buffer_deleter); hb_buffer_pre_allocate(buffer.get(), safe_cast(length)); mapnik::value_unicode_string const& text = itemizer.text(); - for (auto const& text_item : list) { + auto item_length = static_cast(text_item.end - text_item.start); face_set_ptr face_set = font_manager.get_face_set(text_item.format_->face_name, text_item.format_->fontset); double size = text_item.format_->text_size * scale_factor; face_set->set_unscaled_character_sizes(); std::size_t num_faces = face_set->size(); - std::size_t pos = 0; + font_feature_settings const& ff_settings = text_item.format_->ff_settings; int ff_count = safe_cast(ff_settings.count()); @@ -101,41 +101,37 @@ static void shape_text(text_line & line, hb_glyph_info_t glyph; hb_glyph_position_t position; }; - // this table is filled with information for rendering each glyph, so that + // 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 glyphinfos; - unsigned valid_glyphs = 0; - + int valid_glyphs = 0; + std::size_t pos = 0; for (auto const& face : *face_set) { ++pos; hb_buffer_clear_contents(buffer.get()); - hb_buffer_add_utf16(buffer.get(), uchar_to_utf16(text.getBuffer()), text.length(), text_item.start, static_cast(text_item.end - text_item.start)); - hb_buffer_set_direction(buffer.get(), (text_item.dir == UBIDI_RTL)?HB_DIRECTION_RTL:HB_DIRECTION_LTR); + hb_buffer_add_utf16(buffer.get(), uchar_to_utf16(text.getBuffer()), text.length(), text_item.start, item_length); + hb_buffer_set_direction(buffer.get(), (text_item.dir == UBIDI_RTL) ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); hb_buffer_set_script(buffer.get(), _icu_script_to_script(text_item.script)); hb_font_t *font(hb_ft_font_create(face->get_face(), nullptr)); // https://github.com/mapnik/test-data-visual/pull/25 - #if HB_VERSION_MAJOR > 0 - #if HB_VERSION_ATLEAST(1, 0 , 5) - hb_ft_font_set_load_flags(font,FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); - #endif - #endif +#if (HB_VERSION_MAJOR > 0 && HB_VERSION_ATLEAST(1, 0, 5)) + hb_ft_font_set_load_flags(font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); +#endif hb_shape(font, buffer.get(), ff_settings.get_features(), ff_count); hb_font_destroy(font); unsigned num_glyphs = hb_buffer_get_length(buffer.get()); + hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer.get(), &num_glyphs); + hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), &num_glyphs); - // if the number of rendered glyphs has increased, we need to resize the table + // 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_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr); - // Check if all glyphs are valid. - for (unsigned i=0; iglyph_dimensions(g)) - { - g.face = theface; - g.scale_multiplier = size / theface->get_face()->units_per_EM; - //Overwrite default advance with better value provided by HarfBuzz - g.unscaled_advance = gpos.x_advance; - g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier); - double tmp_height = g.height(); - if (tmp_height > max_glyph_height) max_glyph_height = tmp_height; - width_map[char_index] += g.advance(); - line.add_glyph(std::move(g), scale_factor); + auto const& gpos = info.position; + auto const& glyph = info.glyph; + auto const& theface = info.face; + + unsigned char_index = glyph.cluster; + glyph_info g(glyph.codepoint, char_index, text_item.format_); + if (theface->glyph_dimensions(g)) + { + g.face = theface; + g.scale_multiplier = size / theface->get_face()->units_per_EM; + //Overwrite default advance with better value provided by HarfBuzz + g.unscaled_advance = gpos.x_advance; + g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier); + double tmp_height = g.height(); + if (tmp_height > max_glyph_height) max_glyph_height = tmp_height; + width_map[char_index] += g.advance(); + line.add_glyph(std::move(g), scale_factor); + } } } line.update_max_char_height(max_glyph_height);