Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added auto hinting compensation to fix too wide gaps between small glyphs #1746

Merged
merged 6 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/SFML/Graphics/Font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class SFML_GRAPHICS_API Font
/// \return Kerning value for \a first and \a second, in pixels
///
////////////////////////////////////////////////////////////
float getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const;
float getKerning(Uint32 first, Uint32 second, unsigned int characterSize, bool bold = false) const;

////////////////////////////////////////////////////////////
/// \brief Get the line spacing
Expand Down
2 changes: 2 additions & 0 deletions include/SFML/Graphics/Glyph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class SFML_GRAPHICS_API Glyph
// Member data
////////////////////////////////////////////////////////////
float advance; //!< Offset to move horizontally to the next character
int lsb_delta; //!< Left offset after forced autohint. Internally used by getKerning()
int rsb_delta; //!< Right offset after forced autohint. Internally used by getKerning()
eXpl0it3r marked this conversation as resolved.
Show resolved Hide resolved
FloatRect bounds; //!< Bounding rectangle of the glyph, in coordinates relative to the baseline
IntRect textureRect; //!< Texture coordinates of the glyph inside the font's texture
};
Expand Down
21 changes: 16 additions & 5 deletions src/SFML/Graphics/Font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include FT_STROKER_H
#include <cstdlib>
#include <cstring>
#include <cmath>


namespace
Expand Down Expand Up @@ -375,30 +376,37 @@ bool Font::hasGlyph(Uint32 codePoint) const


////////////////////////////////////////////////////////////
float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const
float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize, bool bold) const
{
// Special case where first or second is 0 (null character)
if (first == 0 || second == 0)
return 0.f;

FT_Face face = static_cast<FT_Face>(m_face);

if (face && FT_HAS_KERNING(face) && setCurrentSize(characterSize))
if (face && setCurrentSize(characterSize))
eXpl0it3r marked this conversation as resolved.
Show resolved Hide resolved
{
// Convert the characters to indices
FT_UInt index1 = FT_Get_Char_Index(face, first);
FT_UInt index2 = FT_Get_Char_Index(face, second);

// Retrieve position compensation deltas generated by FT_LOAD_FORCE_AUTOHINT flag
float firstRsbDelta = getGlyph(first, characterSize, bold).rsb_delta;
float secondLsbDelta = getGlyph(second, characterSize, bold).lsb_delta;

// Get the kerning vector
FT_Vector kerning;
FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning);
kerning.x = kerning.y = 0;
if( FT_HAS_KERNING(face))
eXpl0it3r marked this conversation as resolved.
Show resolved Hide resolved
FT_Get_Kerning(face, index1, index2, FT_KERNING_UNFITTED, &kerning);

// X advance is already in pixels for bitmap fonts
if (!FT_IS_SCALABLE(face))
return static_cast<float>(kerning.x);

// Return the X advance
return static_cast<float>(kerning.x) / static_cast<float>(1 << 6);
// Combine kerning with compensation deltas and return the X advance
// Flooring is required as we use FT_KERNING_UNFITTED flag which is not quantized in 64 based grid
return std::floor((secondLsbDelta - firstRsbDelta + static_cast<float>(kerning.x) + 32) / static_cast<float>(1 << 6));
}
else
{
Expand Down Expand Up @@ -624,6 +632,9 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
if (bold)
glyph.advance += static_cast<float>(weight) / static_cast<float>(1 << 6);

glyph.lsb_delta = face->glyph->lsb_delta;
glyph.rsb_delta = face->glyph->rsb_delta;

int width = bitmap.width;
int height = bitmap.rows;

Expand Down
4 changes: 2 additions & 2 deletions src/SFML/Graphics/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ Vector2f Text::findCharacterPos(std::size_t index) const
Uint32 curChar = m_string[i];

// Apply the kerning offset
position.x += m_font->getKerning(prevChar, curChar, m_characterSize);
position.x += m_font->getKerning(prevChar, curChar, m_characterSize, isBold);
prevChar = curChar;

// Handle special characters
Expand Down Expand Up @@ -451,7 +451,7 @@ void Text::ensureGeometryUpdate() const
continue;

// Apply the kerning offset
x += m_font->getKerning(prevChar, curChar, m_characterSize);
x += m_font->getKerning(prevChar, curChar, m_characterSize, isBold);

// If we're using the underlined style and there's a new line, draw a line
if (isUnderlined && (curChar == L'\n' && prevChar != L'\n'))
Expand Down