diff --git a/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.cpp b/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.cpp index 6d7f871a5..3f7084331 100644 --- a/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.cpp +++ b/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.cpp @@ -68,12 +68,10 @@ bool FontFaceHandleHarfBuzz::Initialize(FontFaceHandleFreetype face, int font_si if (!FreeType::InitialiseFaceHandle(ft_face, font_size, glyphs, metrics, load_default_glyphs)) return false; - has_kerning = Rml::FreeType::HasKerning(ft_face); - FillKerningPairCache(); - hb_font = hb_ft_font_create_referenced((FT_Face)ft_face); RMLUI_ASSERT(hb_font != nullptr); hb_font_set_ptem(hb_font, (float)font_size); + hb_ft_font_set_funcs(hb_font); // Generate the default layer and layer configuration. base_layer = GetOrCreateLayer(nullptr); @@ -98,7 +96,7 @@ const FallbackFontGlyphMap& FontFaceHandleHarfBuzz::GetFallbackGlyphs() const } int FontFaceHandleHarfBuzz::GetStringWidth(StringView string, const TextShapingContext& text_shaping_context, - const LanguageDataMap& registered_languages, Character prior_character) + const LanguageDataMap& registered_languages, Character /*prior_character*/) { int width = 0; @@ -109,10 +107,9 @@ int FontFaceHandleHarfBuzz::GetStringWidth(StringView string, const TextShapingC hb_buffer_add_utf8(shaping_buffer, string.begin(), (int)string.size(), 0, (int)string.size()); hb_shape(hb_font, shaping_buffer, nullptr, 0); - FontGlyphIndex prior_glyph_codepoint = FreeType::GetGlyphIndexFromCharacter(ft_face, prior_character); - unsigned int glyph_count = 0; hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(shaping_buffer, &glyph_count); + hb_glyph_position_t* glyph_positions = hb_buffer_get_glyph_positions(shaping_buffer, &glyph_count); for (int g = 0; g < (int)glyph_count; ++g) { @@ -121,19 +118,19 @@ int FontFaceHandleHarfBuzz::GetStringWidth(StringView string, const TextShapingC if (IsASCIIControlCharacter(character)) continue; - FontGlyphIndex glyph_codepoint = glyph_info[g].codepoint; - const FontGlyph* glyph = GetOrAppendGlyph(glyph_codepoint, character); + FontGlyphIndex glyph_index = glyph_info[g].codepoint; + const FontGlyph* glyph = GetOrAppendGlyph(glyph_index, character); if (!glyph) continue; - // Adjust the cursor for the kerning between this character and the previous one. - width += GetKerning(prior_glyph_codepoint, glyph_codepoint); - // Adjust the cursor for this character's advance. - width += glyph->advance; - width += (int)text_shaping_context.letter_spacing; + if (glyph_index != 0) + width += glyph_positions[g].x_advance >> 6; + else + // Use the unshaped advance for unsupported characters. + width += glyph->advance; - prior_glyph_codepoint = glyph_codepoint; + width += (int)text_shaping_context.letter_spacing; } hb_buffer_destroy(shaping_buffer); @@ -265,7 +262,6 @@ int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, Textur RMLUI_ASSERT(geometry_index + num_textures <= (int)mesh_list.size()); line_width = 0; - FontGlyphIndex prior_glyph_codepoint = 0; // Set the mesh and textures to the geometries. for (int tex_index = 0; tex_index < num_textures; ++tex_index) @@ -279,6 +275,7 @@ int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, Textur unsigned int glyph_count = 0; hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(shaping_buffer, &glyph_count); + hb_glyph_position_t* glyph_positions = hb_buffer_get_glyph_positions(shaping_buffer, &glyph_count); mesh_list[geometry_index].mesh.indices.reserve(string.size() * 6); mesh_list[geometry_index].mesh.vertices.reserve(string.size() * 4); @@ -291,25 +288,28 @@ int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, Textur if (IsASCIIControlCharacter(character)) continue; - FontGlyphIndex glyph_codepoint = glyph_info[g].codepoint; - const FontGlyph* glyph = GetOrAppendGlyph(glyph_codepoint, character); + FontGlyphIndex glyph_index = glyph_info[g].codepoint; + const FontGlyph* glyph = GetOrAppendGlyph(glyph_index, character); if (!glyph) continue; - // Adjust the cursor for the kerning between this character and the previous one. - line_width += GetKerning(prior_glyph_codepoint, glyph_codepoint); - ColourbPremultiplied glyph_color = layer_colour; // Use white vertex colors on RGB glyphs. if (layer == base_layer && glyph->color_format == ColorFormat::RGBA8) glyph_color = ColourbPremultiplied(layer_colour.alpha, layer_colour.alpha); - layer->GenerateGeometry(&mesh_list[geometry_index], glyph_codepoint, character, Vector2f(position.x + line_width, position.y), - glyph_color); + Vector2f glyph_offset(glyph_positions[g].x_offset >> 6, glyph_positions[g].y_offset >> 6); + layer->GenerateGeometry(&mesh_list[geometry_index], glyph_index, character, + Vector2f(position.x + line_width, position.y) + glyph_offset, glyph_color); + + // Adjust the cursor for this character's advance. + if (glyph_index != 0) + line_width += glyph_positions[g].x_advance >> 6; + else + // Use the unshaped advance for unsupported characters. + line_width += glyph->advance; - line_width += glyph->advance; line_width += (int)text_shaping_context.letter_spacing; - prior_glyph_codepoint = glyph_codepoint; } geometry_index += num_textures; @@ -383,49 +383,6 @@ bool FontFaceHandleHarfBuzz::AppendFallbackGlyph(Character character) return false; } -void FontFaceHandleHarfBuzz::FillKerningPairCache() -{ - if (!has_kerning) - return; - - static constexpr char32_t KerningCache_AsciiSubsetBegin = 32; - static constexpr char32_t KerningCache_AsciiSubsetLast = 126; - - for (char32_t i = KerningCache_AsciiSubsetBegin; i <= KerningCache_AsciiSubsetLast; i++) - { - for (char32_t j = KerningCache_AsciiSubsetBegin; j <= KerningCache_AsciiSubsetLast; j++) - { - const bool first_iteration = (i == KerningCache_AsciiSubsetBegin && j == KerningCache_AsciiSubsetBegin); - - // Fetch the kerning from the font face. Submit zero font size on subsequent iterations for performance reasons. - const int kerning = FreeType::GetKerning(ft_face, first_iteration ? metrics.size : 0, - FreeType::GetGlyphIndexFromCharacter(ft_face, Character(i)), FreeType::GetGlyphIndexFromCharacter(ft_face, Character(j))); - if (kerning != 0) - { - kerning_pair_cache.emplace(AsciiPair((i << 8) | j), KerningIntType(kerning)); - } - } - } -} - -int FontFaceHandleHarfBuzz::GetKerning(FontGlyphIndex lhs, FontGlyphIndex rhs) const -{ - // Check if we have no kerning, or if we are have an unsupported character. - if (!has_kerning || lhs == 0 || rhs == 0) - return 0; - - // See if the kerning pair has been cached. - const auto it = kerning_pair_cache.find(AsciiPair((int(lhs) << 8) | int(rhs))); - if (it != kerning_pair_cache.end()) - { - return it->second; - } - - // Fetch it from the font face instead. - const int result = FreeType::GetKerning(ft_face, metrics.size, lhs, rhs); - return result; -} - const FontGlyph* FontFaceHandleHarfBuzz::GetOrAppendGlyph(FontGlyphIndex glyph_index, Character& character, bool look_in_fallback_fonts) { if (glyph_index == 0 && look_in_fallback_fonts && character != Character::Replacement) diff --git a/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.h b/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.h index 2a0a9bc73..db5252e37 100644 --- a/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.h +++ b/Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.h @@ -119,12 +119,6 @@ class FontFaceHandleHarfBuzz : public Rml::NonCopyMoveable { // Build and append fallback glyph to 'fallback_glyphs'. bool AppendFallbackGlyph(Character character); - // Build a kerning cache for common characters. - void FillKerningPairCache(); - - // Return the kerning for a codepoint pair. - int GetKerning(FontGlyphIndex lhs, FontGlyphIndex rhs) const; - /// Retrieve a glyph from the given code index, building and appending a new glyph if not already built. /// @param[in] glyph_index The glyph index. /// @param[in-out] character The character codepoint, can be changed e.g. to the replacement character if no glyph is found.. @@ -168,13 +162,6 @@ class FontFaceHandleHarfBuzz : public Rml::NonCopyMoveable { // Each font layer that generated geometry or textures, indexed by the font-effect's fingerprint key. FontLayerCache layer_cache; - // Pre-cache kerning pairs for some ascii subset of all characters. - using AsciiPair = uint16_t; - using KerningIntType = int16_t; - using KerningPairs = UnorderedMap; - KerningPairs kerning_pair_cache; - - bool has_kerning = false; bool is_layers_dirty = false; int version = 0; diff --git a/Samples/basic/harfbuzz/src/FreeTypeInterface.cpp b/Samples/basic/harfbuzz/src/FreeTypeInterface.cpp index c5528501c..8140c1f93 100644 --- a/Samples/basic/harfbuzz/src/FreeTypeInterface.cpp +++ b/Samples/basic/harfbuzz/src/FreeTypeInterface.cpp @@ -80,32 +80,6 @@ bool AppendGlyph(FontFaceHandleFreetype face, int font_size, FontGlyphIndex glyp return true; } -int GetKerning(FontFaceHandleFreetype face, int font_size, FontGlyphIndex lhs, FontGlyphIndex rhs) -{ - FT_Face ft_face = (FT_Face)face; - - RMLUI_ASSERT(FT_HAS_KERNING(ft_face)); - - // Set face size again in case it was used at another size in another font face handle. - // Font size value of zero assumes it is already set. - if (font_size > 0) - { - float bitmap_scaling_factor = 1.0f; - if (!SetFontSize(ft_face, font_size, bitmap_scaling_factor) || bitmap_scaling_factor != 1.0f) - return 0; - } - - FT_Vector ft_kerning; - - FT_Error ft_error = FT_Get_Kerning(ft_face, lhs, rhs,FT_KERNING_DEFAULT, &ft_kerning); - - if (ft_error) - return 0; - - int kerning = ft_kerning.x >> 6; - return kerning; -} - FontGlyphIndex GetGlyphIndexFromCharacter(FontFaceHandleFreetype face, Character character) { return FT_Get_Char_Index((FT_Face)face, (FT_ULong)character); diff --git a/Samples/basic/harfbuzz/src/FreeTypeInterface.h b/Samples/basic/harfbuzz/src/FreeTypeInterface.h index 361c2139c..4fc9870cf 100644 --- a/Samples/basic/harfbuzz/src/FreeTypeInterface.h +++ b/Samples/basic/harfbuzz/src/FreeTypeInterface.h @@ -42,10 +42,6 @@ bool InitialiseFaceHandle(FontFaceHandleFreetype face, int font_size, FontGlyphM // Build a new glyph representing the given glyph index and append to 'glyphs'. bool AppendGlyph(FontFaceHandleFreetype face, int font_size, FontGlyphIndex glyph_index, Character character, FontGlyphMap& glyphs); -// Returns the kerning between two characters given by glyph indices. -// 'font_size' value of zero assumes the font size is already set on the face, and skips this step for performance reasons. -int GetKerning(FontFaceHandleFreetype face, int font_size, FontGlyphIndex lhs, FontGlyphIndex rhs); - // Returns the corresponding glyph index from a character code. FontGlyphIndex GetGlyphIndexFromCharacter(FontFaceHandleFreetype face, Character character);