diff options
author | Mike Morris <mikemorris@users.noreply.github.com> | 2016-04-11 16:01:12 -0700 |
---|---|---|
committer | Mike Morris <mikemorris@users.noreply.github.com> | 2016-04-11 16:01:12 -0700 |
commit | 4d647f9a8623eb06dd4d8b0c4e7c40a459ffb2ad (patch) | |
tree | 2015677c21768fd0694a27c6f1e3ad09abd7ed7b | |
parent | 8c7dc19e3f3656d56de82952aed06c5ac8879d50 (diff) | |
download | qtlocation-mapboxgl-4d647f9a8623eb06dd4d8b0c4e7c40a459ffb2ad.tar.gz |
initial integration of harfbuzz
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | mbgl.gypi | 2 | ||||
-rw-r--r-- | platform/linux/scripts/configure.sh | 1 | ||||
-rw-r--r-- | platform/osx/scripts/configure.sh | 1 | ||||
-rw-r--r-- | src/mbgl/text/font_stack.cpp | 119 |
6 files changed, 126 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 218297e317..0f0b3a6439 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ *.gcda *~ offline.db +cache.sqlite +out.png /platform/node/test/actual /platform/node/test/diff /mason_packages @@ -110,6 +110,7 @@ print_flags gtest static_libs cflags ldflags print_flags pixelmatch static_libs cflags ldflags print_flags webp static_libs cflags ldflags print_flags jni.hpp static_libs cflags ldflags +print_flags harfbuzz static_libs cflags ldflags CONFIG+=" } } @@ -172,6 +172,7 @@ '<@(geojsonvt_cflags)', '<@(rapidjson_cflags)', '<@(variant_cflags)', + '<@(harfbuzz_cflags)', ], 'cflags': [ '<@(opengl_cflags)', @@ -183,6 +184,7 @@ ], 'libraries': [ '<@(geojsonvt_static_libs)', + '<@(harfbuzz_static_libs)', ], }, diff --git a/platform/linux/scripts/configure.sh b/platform/linux/scripts/configure.sh index 410faaf442..37812ba611 100644 --- a/platform/linux/scripts/configure.sh +++ b/platform/linux/scripts/configure.sh @@ -16,6 +16,7 @@ RAPIDJSON_VERSION=1.0.2 GTEST_VERSION=1.7.0 PIXELMATCH_VERSION=0.9.0 WEBP_VERSION=0.5.0 +HARFBUZZ_VERSION=1.2.1 function print_opengl_flags { CONFIG+=" 'opengl_cflags%': $(quote_flags $(pkg-config gl x11 --cflags)),"$LN diff --git a/platform/osx/scripts/configure.sh b/platform/osx/scripts/configure.sh index e2fa095df9..6e1585ce2e 100644 --- a/platform/osx/scripts/configure.sh +++ b/platform/osx/scripts/configure.sh @@ -11,3 +11,4 @@ VARIANT_VERSION=1.1.0 RAPIDJSON_VERSION=1.0.2 GTEST_VERSION=1.7.0 PIXELMATCH_VERSION=0.9.0 +HARFBUZZ_VERSION=1.2.1 diff --git a/src/mbgl/text/font_stack.cpp b/src/mbgl/text/font_stack.cpp index 60e90a77e8..c45089a933 100644 --- a/src/mbgl/text/font_stack.cpp +++ b/src/mbgl/text/font_stack.cpp @@ -3,6 +3,11 @@ #include <mbgl/platform/log.hpp> #include <mbgl/util/math.hpp> +#include <harfbuzz/hb.h> +// #include <harfbuzz/hb-ft.h> +#include <iostream> +#include <codecvt> + namespace mbgl { void FontStack::insert(uint32_t id, const SDFGlyph &glyph) { @@ -41,6 +46,120 @@ const Shaping FontStack::getShaping(const std::u32string &string, const float ma float x = 0; const float y = yOffset; + // TODO: pass string through harfbuzz + auto hb_buffer_deleter = [](hb_buffer_t * buffer) { hb_buffer_destroy(buffer);}; + const std::unique_ptr<hb_buffer_t, decltype(hb_buffer_deleter)> buffer(hb_buffer_create(),hb_buffer_deleter); + hb_buffer_pre_allocate(buffer.get(), string.length()); + + std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cv; + std::cout << cv.to_bytes(string) << std::endl; + + /* + mapnik::value_unicode_string const& text = itemizer.text(); + + for (auto const& text_item : list) + { + 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<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) + { + ++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<int>(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_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 + hb_shape(font, buffer.get(), ff_settings.get_features(), ff_count); + hb_font_destroy(font); + + 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_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr); + + // Check if all glyphs are valid. + for (unsigned i=0; i<num_glyphs; ++i) + { + // if we have a valid codepoint, save rendering info. + if (glyphs[i].codepoint) + { + if (!glyphinfos[i].glyph.codepoint) + { + ++valid_glyphs; + } + glyphinfos[i] = { face, glyphs[i], positions[i] }; + } + } + if (valid_glyphs < num_glyphs && (pos < num_faces)) + { + //Try next font in fontset + continue; + } + + double max_glyph_height = 0; + for (unsigned i=0; i<num_glyphs; ++i) + { + auto& gpos = positions[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; + 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); + break; //When we reach this point the current font had all glyphs. + } + } + */ + + // Loop through all characters of this label and shape. for (uint32_t chr : string) { auto it = sdfs.find(chr); |