From 4d2e5b18e2107931b389d562d057182bf6eecb85 Mon Sep 17 00:00:00 2001 From: Corentin Schreiber Date: Thu, 7 Oct 2021 07:52:42 +0100 Subject: [PATCH] Fix incorrect glyph rect for text outline --- src/SFML/Graphics/Font.cpp | 15 ++++++++----- src/SFML/Graphics/Text.cpp | 46 +++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index e9d7eb9e..0b285640 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -614,8 +614,11 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f } // Convert the glyph to a bitmap (i.e. rasterize it) + // Warning! After this line, do not read any data from glyphDesc directly, use + // bitmapGlyph.root to access the FT_Glyph data. FT_Glyph_To_Bitmap(&glyphDesc, FT_RENDER_MODE_NORMAL, 0, 1); - FT_Bitmap& bitmap = reinterpret_cast(glyphDesc)->bitmap; + FT_BitmapGlyph bitmapGlyph = reinterpret_cast(glyphDesc); + FT_Bitmap& bitmap = bitmapGlyph->bitmap; // Apply bold if necessary -- fallback technique using bitmap (lower quality) if (!outline) @@ -628,7 +631,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f } // Compute the glyph's advance offset - glyph.advance = static_cast(face->glyph->metrics.horiAdvance) / static_cast(1 << 6); + glyph.advance = std::round(static_cast(bitmapGlyph->root.advance.x) / static_cast(1 << 16)); if (bold) glyph.advance += static_cast(weight) / static_cast(1 << 6); @@ -661,10 +664,10 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f glyph.textureRect.height -= 2 * padding; // Compute the glyph's bounding box - 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) + outlineThickness * 2; - glyph.bounds.height = static_cast(face->glyph->metrics.height) / static_cast(1 << 6) + outlineThickness * 2; + glyph.bounds.left = bitmapGlyph->left; + glyph.bounds.top = -bitmapGlyph->top; + glyph.bounds.width = bitmap.width; + glyph.bounds.height = bitmap.rows; // Resize the pixel buffer to the new size and fill it with transparent white pixels m_pixelBuffer.resize(width * height * 4); diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp index eb2600c7..9915eb88 100644 --- a/src/SFML/Graphics/Text.cpp +++ b/src/SFML/Graphics/Text.cpp @@ -34,21 +34,21 @@ namespace { // Add an underline or strikethrough line to the vertex array - void addLine(sf::VertexArray& vertices, float lineLength, float lineTop, const sf::Color& color, float offset, float thickness, float outlineThickness = 0) + void addLine(sf::VertexArray& vertices, float lineLength, float lineTop, const sf::Color& color, float offset, float thickness) { float top = std::floor(lineTop + offset - (thickness / 2) + 0.5f); float bottom = top + std::floor(thickness + 0.5f); - vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1))); - vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1))); - vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1))); - vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1))); - vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1))); - vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(0, top), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(lineLength, top), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(0, bottom), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(0, bottom), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(lineLength, top), color, sf::Vector2f(1, 1))); + vertices.append(sf::Vertex(sf::Vector2f(lineLength, bottom), color, sf::Vector2f(1, 1))); } // Add a glyph quad to the vertex array - void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear, float outlineThickness = 0) + void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear) { float padding = 1.0; @@ -62,12 +62,12 @@ namespace float u2 = static_cast(glyph.textureRect.left + glyph.textureRect.width) + padding; float v2 = static_cast(glyph.textureRect.top + glyph.textureRect.height) + padding; - vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u1, v1))); - vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1))); - vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2))); - vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2))); - vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1))); - vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u2, v2))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * top , position.y + top), color, sf::Vector2f(u1, v1))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top , position.y + top), color, sf::Vector2f(u2, v1))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom, position.y + bottom), color, sf::Vector2f(u1, v2))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom, position.y + bottom), color, sf::Vector2f(u1, v2))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top , position.y + top), color, sf::Vector2f(u2, v1))); + vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * bottom, position.y + bottom), color, sf::Vector2f(u2, v2))); } } @@ -459,7 +459,7 @@ void Text::ensureGeometryUpdate() const addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness); if (m_outlineThickness != 0) - addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness, m_outlineThickness); + addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness); } // If we're using the strike through style and there's a new line, draw a line across all characters @@ -468,7 +468,7 @@ void Text::ensureGeometryUpdate() const addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness); if (m_outlineThickness != 0) - addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness, m_outlineThickness); + addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness); } prevChar = curChar; @@ -506,13 +506,13 @@ void Text::ensureGeometryUpdate() const float bottom = glyph.bounds.top + glyph.bounds.height; // Add the outline glyph to the vertices - addGlyphQuad(m_outlineVertices, Vector2f(x, y), m_outlineColor, glyph, italicShear, m_outlineThickness); + addGlyphQuad(m_outlineVertices, Vector2f(x, y), m_outlineColor, glyph, italicShear); // Update the current bounds with the outlined glyph bounds - minX = std::min(minX, x + left - italicShear * bottom - m_outlineThickness); - maxX = std::max(maxX, x + right - italicShear * top - m_outlineThickness); - minY = std::min(minY, y + top - m_outlineThickness); - maxY = std::max(maxY, y + bottom - m_outlineThickness); + minX = std::min(minX, x + left - italicShear * bottom); + maxX = std::max(maxX, x + right - italicShear * top); + minY = std::min(minY, y + top); + maxY = std::max(maxY, y + bottom); } // Extract the current glyph's description @@ -545,7 +545,7 @@ void Text::ensureGeometryUpdate() const addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness); if (m_outlineThickness != 0) - addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness, m_outlineThickness); + addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness); } // If we're using the strike through style, add the last line across all characters @@ -554,7 +554,7 @@ void Text::ensureGeometryUpdate() const addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness); if (m_outlineThickness != 0) - addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness, m_outlineThickness); + addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness); } // Update the bounding rectangle