Some simplifications taking advantage of Rect position and size members

This commit is contained in:
kimci86 2024-06-15 19:46:40 +02:00 committed by Vittorio Romeo
parent 65c0a8183c
commit 58e83056bb
7 changed files with 71 additions and 98 deletions

View File

@ -152,8 +152,7 @@ int main()
} }
// Center the status text // Center the status text
statusText.setPosition({(windowWidth - statusText.getLocalBounds().size.x) / 2.f, statusText.setPosition((sf::Vector2f(windowWidth, windowHeight) - statusText.getLocalBounds().size) / 2.f);
(windowHeight - statusText.getLocalBounds().size.y) / 2.f});
// Set up an array of pointers to our settings for arrow navigation // Set up an array of pointers to our settings for arrow navigation
constexpr std::array<Setting, 9> settings = { constexpr std::array<Setting, 9> settings = {

View File

@ -104,30 +104,27 @@ constexpr Vector2f Transform::transformPoint(const Vector2f& point) const
constexpr FloatRect Transform::transformRect(const FloatRect& rectangle) const constexpr FloatRect Transform::transformRect(const FloatRect& rectangle) const
{ {
// Transform the 4 corners of the rectangle // Transform the 4 corners of the rectangle
const std::array points = {transformPoint({rectangle.position.x, rectangle.position.y}), const std::array points = {transformPoint(rectangle.position),
transformPoint({rectangle.position.x, rectangle.position.y + rectangle.size.y}), transformPoint(rectangle.position + Vector2f(0.f, rectangle.size.y)),
transformPoint({rectangle.position.x + rectangle.size.x, rectangle.position.y}), transformPoint(rectangle.position + Vector2f(rectangle.size.x, 0.f)),
transformPoint( transformPoint(rectangle.position + rectangle.size)};
{rectangle.position.x + rectangle.size.x, rectangle.position.y + rectangle.size.y})};
// Compute the bounding rectangle of the transformed points // Compute the bounding rectangle of the transformed points
float left = points[0].x; Vector2f pmin = points[0];
float top = points[0].y; Vector2f pmax = points[0];
float right = points[0].x;
float bottom = points[0].y;
for (std::size_t i = 1; i < points.size(); ++i) for (std::size_t i = 1; i < points.size(); ++i)
{ {
// clang-format off // clang-format off
if (points[i].x < left) left = points[i].x; if (points[i].x < pmin.x) pmin.x = points[i].x;
else if (points[i].x > right) right = points[i].x; else if (points[i].x > pmax.x) pmax.x = points[i].x;
if (points[i].y < top) top = points[i].y; if (points[i].y < pmin.y) pmin.y = points[i].y;
else if (points[i].y > bottom) bottom = points[i].y; else if (points[i].y > pmax.y) pmax.y = points[i].y;
// clang-format on // clang-format on
} }
return {{left, top}, {right - left, bottom - top}}; return {pmin, pmax - pmin};
} }

View File

@ -546,42 +546,36 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
glyph.lsbDelta = static_cast<int>(face->glyph->lsb_delta); glyph.lsbDelta = static_cast<int>(face->glyph->lsb_delta);
glyph.rsbDelta = static_cast<int>(face->glyph->rsb_delta); glyph.rsbDelta = static_cast<int>(face->glyph->rsb_delta);
unsigned int width = bitmap.width; Vector2u size(bitmap.width, bitmap.rows);
unsigned int height = bitmap.rows;
if ((width > 0) && (height > 0)) if ((size.x > 0) && (size.y > 0))
{ {
// Leave a small padding around characters, so that filtering doesn't // Leave a small padding around characters, so that filtering doesn't
// pollute them with pixels from neighbors // pollute them with pixels from neighbors
const unsigned int padding = 2; const unsigned int padding = 2;
width += 2 * padding; size += 2u * Vector2u(padding, padding);
height += 2 * padding;
// Get the glyphs page corresponding to the character size // Get the glyphs page corresponding to the character size
Page& page = loadPage(characterSize); Page& page = loadPage(characterSize);
// Find a good position for the new glyph into the texture // Find a good position for the new glyph into the texture
glyph.textureRect = findGlyphRect(page, {width, height}); glyph.textureRect = findGlyphRect(page, size);
// Make sure the texture data is positioned in the center // Make sure the texture data is positioned in the center
// of the allocated texture rectangle // of the allocated texture rectangle
glyph.textureRect.position.x += static_cast<int>(padding); glyph.textureRect.position += Vector2i(padding, padding);
glyph.textureRect.position.y += static_cast<int>(padding); glyph.textureRect.size -= 2 * Vector2i(padding, padding);
glyph.textureRect.size.x -= static_cast<int>(2 * padding);
glyph.textureRect.size.y -= static_cast<int>(2 * padding);
// Compute the glyph's bounding box // Compute the glyph's bounding box
glyph.bounds.position.x = static_cast<float>(bitmapGlyph->left); glyph.bounds.position = Vector2f(Vector2i(bitmapGlyph->left, -bitmapGlyph->top));
glyph.bounds.position.y = static_cast<float>(-bitmapGlyph->top); glyph.bounds.size = Vector2f(Vector2u(bitmap.width, bitmap.rows));
glyph.bounds.size.x = static_cast<float>(bitmap.width);
glyph.bounds.size.y = static_cast<float>(bitmap.rows);
// Resize the pixel buffer to the new size and fill it with transparent white pixels // Resize the pixel buffer to the new size and fill it with transparent white pixels
m_pixelBuffer.resize(static_cast<std::size_t>(width) * static_cast<std::size_t>(height) * 4); m_pixelBuffer.resize(static_cast<std::size_t>(size.x) * static_cast<std::size_t>(size.y) * 4);
std::uint8_t* current = m_pixelBuffer.data(); std::uint8_t* current = m_pixelBuffer.data();
std::uint8_t* end = current + width * height * 4; std::uint8_t* end = current + size.x * size.y * 4;
while (current != end) while (current != end)
{ {
@ -596,12 +590,12 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
{ {
// Pixels are 1 bit monochrome values // Pixels are 1 bit monochrome values
for (unsigned int y = padding; y < height - padding; ++y) for (unsigned int y = padding; y < size.y - padding; ++y)
{ {
for (unsigned int x = padding; x < width - padding; ++x) for (unsigned int x = padding; x < size.x - padding; ++x)
{ {
// The color channels remain white, just fill the alpha channel // The color channels remain white, just fill the alpha channel
const std::size_t index = x + y * width; const std::size_t index = x + y * size.x;
m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0; m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0;
} }
pixels += bitmap.pitch; pixels += bitmap.pitch;
@ -610,12 +604,12 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
else else
{ {
// Pixels are 8 bits gray levels // Pixels are 8 bits gray levels
for (unsigned int y = padding; y < height - padding; ++y) for (unsigned int y = padding; y < size.y - padding; ++y)
{ {
for (unsigned int x = padding; x < width - padding; ++x) for (unsigned int x = padding; x < size.x - padding; ++x)
{ {
// The color channels remain white, just fill the alpha channel // The color channels remain white, just fill the alpha channel
const std::size_t index = x + y * width; const std::size_t index = x + y * size.x;
m_pixelBuffer[index * 4 + 3] = pixels[x - padding]; m_pixelBuffer[index * 4 + 3] = pixels[x - padding];
} }
pixels += bitmap.pitch; pixels += bitmap.pitch;
@ -623,11 +617,9 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
} }
// Write the pixels to the texture // Write the pixels to the texture
const unsigned int x = static_cast<unsigned int>(glyph.textureRect.position.x) - padding; const auto dest = Vector2u(glyph.textureRect.position) - Vector2u(padding, padding);
const unsigned int y = static_cast<unsigned int>(glyph.textureRect.position.y) - padding; const auto updateSize = Vector2u(glyph.textureRect.size) + 2u * Vector2u(padding, padding);
const unsigned int w = static_cast<unsigned int>(glyph.textureRect.size.x) + 2 * padding; page.texture.update(m_pixelBuffer.data(), updateSize, dest);
const unsigned int h = static_cast<unsigned int>(glyph.textureRect.size.y) + 2 * padding;
page.texture.update(m_pixelBuffer.data(), {w, h}, {x, y});
} }
// Delete the FT glyph // Delete the FT glyph

View File

@ -265,15 +265,14 @@ void Shape::updateTexCoords()
{ {
const FloatRect convertedTextureRect(m_textureRect); const FloatRect convertedTextureRect(m_textureRect);
// Make sure not to divide by zero when the points are aligned on a vertical or horizontal line
const Vector2f safeInsideSize(m_insideBounds.size.x > 0 ? m_insideBounds.size.x : 1.f,
m_insideBounds.size.y > 0 ? m_insideBounds.size.y : 1.f);
for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i) for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
{ {
const float xratio = m_insideBounds.size.x > 0 const Vector2f ratio = (m_vertices[i].position - m_insideBounds.position).cwiseDiv(safeInsideSize);
? (m_vertices[i].position.x - m_insideBounds.position.x) / m_insideBounds.size.x m_vertices[i].texCoords = convertedTextureRect.position + convertedTextureRect.size.cwiseMul(ratio);
: 0;
const float yratio = m_insideBounds.size.y > 0
? (m_vertices[i].position.y - m_insideBounds.position.y) / m_insideBounds.size.y
: 0;
m_vertices[i].texCoords = convertedTextureRect.position + convertedTextureRect.size.cwiseMul({xratio, yratio});
} }
} }

View File

@ -128,28 +128,22 @@ void Sprite::draw(RenderTarget& target, RenderStates states) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sprite::updateVertices() void Sprite::updateVertices()
{ {
const auto left = static_cast<float>(m_textureRect.position.x); const auto [position, size] = FloatRect(m_textureRect);
const auto top = static_cast<float>(m_textureRect.position.y);
const auto width = static_cast<float>(m_textureRect.size.x);
const auto height = static_cast<float>(m_textureRect.size.y);
const auto right = float{left + width};
const auto bottom = float{top + height};
// Absolute value is used to support negative texture rect sizes // Absolute value is used to support negative texture rect sizes
const auto absWidth = float{std::abs(width)}; const Vector2f absSize(std::abs(size.x), std::abs(size.y));
const auto absHeight = float{std::abs(height)};
// Update positions // Update positions
m_vertices[0].position = {0.f, 0.f}; m_vertices[0].position = {0.f, 0.f};
m_vertices[1].position = {0.f, absHeight}; m_vertices[1].position = {0.f, absSize.y};
m_vertices[2].position = {absWidth, 0.f}; m_vertices[2].position = {absSize.x, 0.f};
m_vertices[3].position = {absWidth, absHeight}; m_vertices[3].position = absSize;
// Update texture coordinates // Update texture coordinates
m_vertices[0].texCoords = {left, top}; m_vertices[0].texCoords = position;
m_vertices[1].texCoords = {left, bottom}; m_vertices[1].texCoords = position + Vector2f(0.f, size.y);
m_vertices[2].texCoords = {right, top}; m_vertices[2].texCoords = position + Vector2f(size.x, 0.f);
m_vertices[3].texCoords = {right, bottom}; m_vertices[3].texCoords = position + size;
} }
} // namespace sf } // namespace sf

View File

@ -63,24 +63,20 @@ void addLine(sf::VertexArray& vertices,
// Add a glyph quad to the vertex array // 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) void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear)
{ {
const float padding = 1.0; const sf::Vector2f padding(1.f, 1.f);
const float left = glyph.bounds.position.x - padding; const sf::Vector2f p1 = glyph.bounds.position - padding;
const float top = glyph.bounds.position.y - padding; const sf::Vector2f p2 = glyph.bounds.position + glyph.bounds.size + padding;
const float right = glyph.bounds.position.x + glyph.bounds.size.x + padding;
const float bottom = glyph.bounds.position.y + glyph.bounds.size.y + padding;
const float u1 = static_cast<float>(glyph.textureRect.position.x) - padding; const auto uv1 = sf::Vector2f(glyph.textureRect.position) - padding;
const float v1 = static_cast<float>(glyph.textureRect.position.y) - padding; const auto uv2 = sf::Vector2f(glyph.textureRect.position + glyph.textureRect.size) + padding;
const float u2 = static_cast<float>(glyph.textureRect.position.x + glyph.textureRect.size.x) + padding;
const float v2 = static_cast<float>(glyph.textureRect.position.y + glyph.textureRect.size.y) + padding;
vertices.append({{position.x + left - italicShear * top, position.y + top}, color, {u1, v1}}); vertices.append({position + sf::Vector2f(p1.x - italicShear * p1.y, p1.y), color, {uv1.x, uv1.y}});
vertices.append({{position.x + right - italicShear * top, position.y + top}, color, {u2, v1}}); vertices.append({position + sf::Vector2f(p2.x - italicShear * p1.y, p1.y), color, {uv2.x, uv1.y}});
vertices.append({{position.x + left - italicShear * bottom, position.y + bottom}, color, {u1, v2}}); vertices.append({position + sf::Vector2f(p1.x - italicShear * p2.y, p2.y), color, {uv1.x, uv2.y}});
vertices.append({{position.x + left - italicShear * bottom, position.y + bottom}, color, {u1, v2}}); vertices.append({position + sf::Vector2f(p1.x - italicShear * p2.y, p2.y), color, {uv1.x, uv2.y}});
vertices.append({{position.x + right - italicShear * top, position.y + top}, color, {u2, v1}}); vertices.append({position + sf::Vector2f(p2.x - italicShear * p1.y, p1.y), color, {uv2.x, uv1.y}});
vertices.append({{position.x + right - italicShear * bottom, position.y + bottom}, color, {u2, v2}}); vertices.append({position + sf::Vector2f(p2.x - italicShear * p2.y, p2.y), color, {uv2.x, uv2.y}});
} }
} // namespace } // namespace
@ -478,15 +474,13 @@ void Text::ensureGeometryUpdate() const
addGlyphQuad(m_vertices, Vector2f(x, y), m_fillColor, glyph, italicShear); addGlyphQuad(m_vertices, Vector2f(x, y), m_fillColor, glyph, italicShear);
// Update the current bounds // Update the current bounds
const float left = glyph.bounds.position.x; const Vector2f p1 = glyph.bounds.position;
const float top = glyph.bounds.position.y; const Vector2f p2 = glyph.bounds.position + glyph.bounds.size;
const float right = glyph.bounds.position.x + glyph.bounds.size.x;
const float bottom = glyph.bounds.position.y + glyph.bounds.size.y;
minX = std::min(minX, x + left - italicShear * bottom); minX = std::min(minX, x + p1.x - italicShear * p2.y);
maxX = std::max(maxX, x + right - italicShear * top); maxX = std::max(maxX, x + p2.x - italicShear * p1.y);
minY = std::min(minY, y + top); minY = std::min(minY, y + p1.y);
maxY = std::max(maxY, y + bottom); maxY = std::max(maxY, y + p2.y);
// Advance to the next character // Advance to the next character
x += glyph.advance + letterSpacing; x += glyph.advance + letterSpacing;
@ -521,10 +515,8 @@ void Text::ensureGeometryUpdate() const
} }
// Update the bounding rectangle // Update the bounding rectangle
m_bounds.position.x = minX; m_bounds.position = Vector2f(minX, minY);
m_bounds.position.y = minY; m_bounds.size = Vector2f(maxX, maxY) - Vector2f(minX, minY);
m_bounds.size.x = maxX - minX;
m_bounds.size.y = maxY - minY;
} }
} // namespace sf } // namespace sf

View File

@ -300,11 +300,11 @@ std::optional<Texture> Texture::loadFromStream(InputStream& stream, bool sRgb, c
std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area) std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area)
{ {
// Retrieve the image size // Retrieve the image size
const auto [width, height] = Vector2i(image.getSize()); const auto size = Vector2i(image.getSize());
// Load the entire image if the source area is either empty or contains the whole image // Load the entire image if the source area is either empty or contains the whole image
if (area.size.x == 0 || (area.size.y == 0) || if (area.size.x == 0 || (area.size.y == 0) ||
((area.position.x <= 0) && (area.position.y <= 0) && (area.size.x >= width) && (area.size.y >= height))) ((area.position.x <= 0) && (area.position.y <= 0) && (area.size.x >= size.x) && (area.size.y >= size.y)))
{ {
// Load the entire image // Load the entire image
if (auto texture = sf::Texture::create(image.getSize(), sRgb)) if (auto texture = sf::Texture::create(image.getSize(), sRgb))
@ -326,8 +326,8 @@ std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, con
IntRect rectangle = area; IntRect rectangle = area;
rectangle.position.x = std::max(rectangle.position.x, 0); rectangle.position.x = std::max(rectangle.position.x, 0);
rectangle.position.y = std::max(rectangle.position.y, 0); rectangle.position.y = std::max(rectangle.position.y, 0);
rectangle.size.x = std::min(rectangle.size.x, width - rectangle.position.x); rectangle.size.x = std::min(rectangle.size.x, size.x - rectangle.position.x);
rectangle.size.y = std::min(rectangle.size.y, height - rectangle.position.y); rectangle.size.y = std::min(rectangle.size.y, size.y - rectangle.position.y);
// Create the texture and upload the pixels // Create the texture and upload the pixels
if (auto texture = sf::Texture::create(Vector2u(rectangle.size), sRgb)) if (auto texture = sf::Texture::create(Vector2u(rectangle.size), sRgb))
@ -338,12 +338,12 @@ std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, con
const priv::TextureSaver save; const priv::TextureSaver save;
// Copy the pixels to the texture, row by row // Copy the pixels to the texture, row by row
const std::uint8_t* pixels = image.getPixelsPtr() + 4 * (rectangle.position.x + (width * rectangle.position.y)); const std::uint8_t* pixels = image.getPixelsPtr() + 4 * (rectangle.position.x + (size.x * rectangle.position.y));
glCheck(glBindTexture(GL_TEXTURE_2D, texture->m_texture)); glCheck(glBindTexture(GL_TEXTURE_2D, texture->m_texture));
for (int i = 0; i < rectangle.size.y; ++i) for (int i = 0; i < rectangle.size.y; ++i)
{ {
glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.size.x, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.size.x, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
pixels += 4 * width; pixels += 4 * size.x;
} }
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));