diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index f40e4a6d0..64efaa559 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -181,7 +181,7 @@ public : /// \return Kerning value for \a first and \a second, in pixels /// //////////////////////////////////////////////////////////// - int getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const; + float getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const; //////////////////////////////////////////////////////////// /// \brief Get the line spacing @@ -194,7 +194,7 @@ public : /// \return Line spacing, in pixels /// //////////////////////////////////////////////////////////// - int getLineSpacing(unsigned int characterSize) const; + float getLineSpacing(unsigned int characterSize) const; //////////////////////////////////////////////////////////// /// \brief Get the position of the underline @@ -209,7 +209,7 @@ public : /// \see getUnderlineThickness /// //////////////////////////////////////////////////////////// - int getUnderlinePosition(unsigned int characterSize) const; + float getUnderlinePosition(unsigned int characterSize) const; //////////////////////////////////////////////////////////// /// \brief Get the thickness of the underline @@ -223,7 +223,7 @@ public : /// \see getUnderlinePosition /// //////////////////////////////////////////////////////////// - int getUnderlineThickness(unsigned int characterSize) const; + float getUnderlineThickness(unsigned int characterSize) const; //////////////////////////////////////////////////////////// /// \brief Retrieve the texture containing the loaded glyphs of a certain size diff --git a/include/SFML/Graphics/Glyph.hpp b/include/SFML/Graphics/Glyph.hpp index 85d0e6f8e..f35f59e69 100644 --- a/include/SFML/Graphics/Glyph.hpp +++ b/include/SFML/Graphics/Glyph.hpp @@ -51,9 +51,9 @@ public : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - int advance; ///< Offset to move horizontically to the next character - IntRect bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - IntRect textureRect; ///< Texture coordinates of the glyph inside the font's texture + float advance; ///< Offset to move horizontically to the next character + 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 }; } // namespace sf diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index 59ae60dd6..a0510ae8b 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -314,11 +314,11 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b //////////////////////////////////////////////////////////// -int Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const +float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const { // Special case where first or second is 0 (null character) if (first == 0 || second == 0) - return 0; + return 0.f; FT_Face face = static_cast(m_face); @@ -334,37 +334,37 @@ int Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) co // X advance is already in pixels for bitmap fonts if (!FT_IS_SCALABLE(face)) - return kerning.x; + return static_cast(kerning.x); // Return the X advance - return kerning.x >> 6; + return static_cast(kerning.x) / static_cast(1 << 6); } else { // Invalid font, or no kerning - return 0; + return 0.f; } } //////////////////////////////////////////////////////////// -int Font::getLineSpacing(unsigned int characterSize) const +float Font::getLineSpacing(unsigned int characterSize) const { FT_Face face = static_cast(m_face); if (face && setCurrentSize(characterSize)) { - return (face->size->metrics.height >> 6); + return static_cast(face->size->metrics.height) / static_cast(1 << 6); } else { - return 0; + return 0.f; } } //////////////////////////////////////////////////////////// -int Font::getUnderlinePosition(unsigned int characterSize) const +float Font::getUnderlinePosition(unsigned int characterSize) const { FT_Face face = static_cast(m_face); @@ -372,19 +372,19 @@ int Font::getUnderlinePosition(unsigned int characterSize) const { // Return a fixed position if font is a bitmap font if (!FT_IS_SCALABLE(face)) - return characterSize / 10; + return characterSize / 10.f; - return (FT_MulFix(face->underline_position, face->size->metrics.y_scale) >> 6); + return -static_cast(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / static_cast(1 << 6); } else { - return 0; + return 0.f; } } //////////////////////////////////////////////////////////// -int Font::getUnderlineThickness(unsigned int characterSize) const +float Font::getUnderlineThickness(unsigned int characterSize) const { FT_Face face = static_cast(m_face); @@ -392,13 +392,13 @@ int Font::getUnderlineThickness(unsigned int characterSize) const { // Return a fixed thickness if font is a bitmap font if (!FT_IS_SCALABLE(face)) - return characterSize / 14; + return characterSize / 14.f; - return (FT_MulFix(face->underline_thickness, face->size->metrics.y_scale) >> 6); + return static_cast(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / static_cast(1 << 6); } else { - return 0; + return 0.f; } } @@ -501,8 +501,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c // Convert the glyph to a bitmap (i.e. rasterize it) FT_Glyph_To_Bitmap(&glyphDesc, FT_RENDER_MODE_NORMAL, 0, 1); - FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyphDesc; - FT_Bitmap& bitmap = bitmapGlyph->bitmap; + FT_Bitmap& bitmap = reinterpret_cast(glyphDesc)->bitmap; // Apply bold if necessary -- fallback technique using bitmap (lower quality) if (bold && !outline) @@ -511,17 +510,12 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c } // Compute the glyph's advance offset - glyph.advance = glyphDesc->advance.x >> 16; + glyph.advance = static_cast(face->glyph->metrics.horiAdvance) / static_cast(1 << 6); if (bold) - glyph.advance += weight >> 6; + glyph.advance += static_cast(weight) / static_cast(1 << 6); int width = bitmap.width; int height = bitmap.rows; - int ascender = face->size->metrics.ascender >> 6; - - // Offset to make up for empty space between ascender and virtual top of the typeface - // Only applied to scalable fonts i.e. not to bitmap fonts - int offset = FT_IS_SCALABLE(face) ? (characterSize - ascender) : 0; if ((width > 0) && (height > 0)) { @@ -535,11 +529,18 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c // Find a good position for the new glyph into the texture glyph.textureRect = findGlyphRect(page, width + 2 * padding, height + 2 * padding); + // Make sure the texture data is positioned in the centre + // of the allocated texture rectangle + glyph.textureRect.left += padding; + glyph.textureRect.top += padding; + glyph.textureRect.width -= 2 * padding; + glyph.textureRect.height -= 2 * padding; + // Compute the glyph's bounding box - glyph.bounds.left = bitmapGlyph->left - padding; - glyph.bounds.top = -bitmapGlyph->top - padding - offset; - glyph.bounds.width = width + 2 * padding; - glyph.bounds.height = height + 2 * padding; + glyph.bounds.left = static_cast(face->glyph->metrics.horiBearingX) / static_cast(1 << 6); + glyph.bounds.top = -static_cast(face->glyph->metrics.horiBearingY) / static_cast(1 << 6); + glyph.bounds.width = static_cast(face->glyph->metrics.width) / static_cast(1 << 6); + glyph.bounds.height = static_cast(face->glyph->metrics.height) / static_cast(1 << 6); // Extract the glyph's pixels from the bitmap m_pixelBuffer.resize(width * height * 4, 255); @@ -574,10 +575,10 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c } // Write the pixels to the texture - unsigned int x = glyph.textureRect.left + padding; - unsigned int y = glyph.textureRect.top + padding; - unsigned int w = glyph.textureRect.width - 2 * padding; - unsigned int h = glyph.textureRect.height - 2 * padding; + unsigned int x = glyph.textureRect.left; + unsigned int y = glyph.textureRect.top; + unsigned int w = glyph.textureRect.width; + unsigned int h = glyph.textureRect.height; page.texture.update(&m_pixelBuffer[0], w, h, x, y); } diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp index aaec8892a..f333b501c 100644 --- a/src/SFML/Graphics/Text.cpp +++ b/src/SFML/Graphics/Text.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace sf @@ -262,14 +263,14 @@ void Text::ensureGeometryUpdate() const bool underlined = (m_style & Underlined) != 0; bool strikeThrough = (m_style & StrikeThrough) != 0; float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees - float underlineOffset = static_cast(m_font->getUnderlinePosition(m_characterSize)); - float underlineThickness = static_cast(m_font->getUnderlineThickness(m_characterSize)); + float underlineOffset = m_font->getUnderlinePosition(m_characterSize); + float underlineThickness = m_font->getUnderlineThickness(m_characterSize); // Compute the location of the strike through dynamically // We use the center point of the lowercase 'x' glyph as the reference // We reuse the underline thickness as the thickness of the strike through as well - IntRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds; - float strikeThroughOffset = static_cast(xBounds.top) + static_cast(xBounds.height) / 2.f; + FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds; + float strikeThroughOffset = xBounds.top + xBounds.height / 2.f; // Precompute the variables needed by the algorithm float hspace = static_cast(m_font->getGlyph(L' ', m_characterSize, bold).advance); @@ -294,8 +295,8 @@ void Text::ensureGeometryUpdate() const // If we're using the underlined style and there's a new line, draw a line if (underlined && (curChar == L'\n')) { - float top = y + underlineOffset; - float bottom = top + underlineThickness; + float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); @@ -308,8 +309,8 @@ void Text::ensureGeometryUpdate() const // If we're using the strike through style and there's a new line, draw a line across all characters if (strikeThrough && (curChar == L'\n')) { - float top = y + strikeThroughOffset; - float bottom = top + underlineThickness; + float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); @@ -344,10 +345,10 @@ void Text::ensureGeometryUpdate() const // Extract the current glyph's description const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold); - int left = glyph.bounds.left; - int top = glyph.bounds.top; - int right = glyph.bounds.left + glyph.bounds.width; - int bottom = glyph.bounds.top + glyph.bounds.height; + float left = glyph.bounds.left; + float top = glyph.bounds.top; + float right = glyph.bounds.left + glyph.bounds.width; + float bottom = glyph.bounds.top + glyph.bounds.height; float u1 = static_cast(glyph.textureRect.left); float v1 = static_cast(glyph.textureRect.top); @@ -375,8 +376,8 @@ void Text::ensureGeometryUpdate() const // If we're using the underlined style, add the last line if (underlined) { - float top = y + underlineOffset; - float bottom = top + underlineThickness; + float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); @@ -389,8 +390,8 @@ void Text::ensureGeometryUpdate() const // If we're using the strike through style, add the last line across all characters if (strikeThrough) { - float top = y + strikeThroughOffset; - float bottom = top + underlineThickness; + float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));