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

Fix incorrect glyph rect for text outline #1827

Merged
merged 2 commits into from Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 9 additions & 6 deletions src/SFML/Graphics/Font.cpp
Expand Up @@ -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<FT_BitmapGlyph>(glyphDesc)->bitmap;
FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyphDesc);
FT_Bitmap& bitmap = bitmapGlyph->bitmap;

// Apply bold if necessary -- fallback technique using bitmap (lower quality)
if (!outline)
Expand All @@ -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<float>(face->glyph->metrics.horiAdvance) / static_cast<float>(1 << 6);
glyph.advance = static_cast<float>(bitmapGlyph->root.advance.x >> 16);
if (bold)
glyph.advance += static_cast<float>(weight) / static_cast<float>(1 << 6);

Expand Down Expand Up @@ -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<float>(face->glyph->metrics.horiBearingX) / static_cast<float>(1 << 6);
glyph.bounds.top = -static_cast<float>(face->glyph->metrics.horiBearingY) / static_cast<float>(1 << 6);
glyph.bounds.width = static_cast<float>(face->glyph->metrics.width) / static_cast<float>(1 << 6) + outlineThickness * 2;
glyph.bounds.height = static_cast<float>(face->glyph->metrics.height) / static_cast<float>(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);
Expand Down
46 changes: 23 additions & 23 deletions src/SFML/Graphics/Text.cpp
Expand Up @@ -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;

Expand All @@ -62,12 +62,12 @@ namespace
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width) + padding;
float v2 = static_cast<float>(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)));
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down