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
statusText.setPosition({(windowWidth - statusText.getLocalBounds().size.x) / 2.f,
(windowHeight - statusText.getLocalBounds().size.y) / 2.f});
statusText.setPosition((sf::Vector2f(windowWidth, windowHeight) - statusText.getLocalBounds().size) / 2.f);
// Set up an array of pointers to our settings for arrow navigation
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
{
// Transform the 4 corners of the rectangle
const std::array points = {transformPoint({rectangle.position.x, rectangle.position.y}),
transformPoint({rectangle.position.x, rectangle.position.y + rectangle.size.y}),
transformPoint({rectangle.position.x + rectangle.size.x, rectangle.position.y}),
transformPoint(
{rectangle.position.x + rectangle.size.x, rectangle.position.y + rectangle.size.y})};
const std::array points = {transformPoint(rectangle.position),
transformPoint(rectangle.position + Vector2f(0.f, rectangle.size.y)),
transformPoint(rectangle.position + Vector2f(rectangle.size.x, 0.f)),
transformPoint(rectangle.position + rectangle.size)};
// Compute the bounding rectangle of the transformed points
float left = points[0].x;
float top = points[0].y;
float right = points[0].x;
float bottom = points[0].y;
Vector2f pmin = points[0];
Vector2f pmax = points[0];
for (std::size_t i = 1; i < points.size(); ++i)
{
// clang-format off
if (points[i].x < left) left = points[i].x;
else if (points[i].x > right) right = points[i].x;
if (points[i].x < pmin.x) pmin.x = points[i].x;
else if (points[i].x > pmax.x) pmax.x = points[i].x;
if (points[i].y < top) top = points[i].y;
else if (points[i].y > bottom) bottom = points[i].y;
if (points[i].y < pmin.y) pmin.y = points[i].y;
else if (points[i].y > pmax.y) pmax.y = points[i].y;
// 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.rsbDelta = static_cast<int>(face->glyph->rsb_delta);
unsigned int width = bitmap.width;
unsigned int height = bitmap.rows;
Vector2u size(bitmap.width, 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
// pollute them with pixels from neighbors
const unsigned int padding = 2;
width += 2 * padding;
height += 2 * padding;
size += 2u * Vector2u(padding, padding);
// Get the glyphs page corresponding to the character size
Page& page = loadPage(characterSize);
// 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
// of the allocated texture rectangle
glyph.textureRect.position.x += static_cast<int>(padding);
glyph.textureRect.position.y += static_cast<int>(padding);
glyph.textureRect.size.x -= static_cast<int>(2 * padding);
glyph.textureRect.size.y -= static_cast<int>(2 * padding);
glyph.textureRect.position += Vector2i(padding, padding);
glyph.textureRect.size -= 2 * Vector2i(padding, padding);
// Compute the glyph's bounding box
glyph.bounds.position.x = static_cast<float>(bitmapGlyph->left);
glyph.bounds.position.y = static_cast<float>(-bitmapGlyph->top);
glyph.bounds.size.x = static_cast<float>(bitmap.width);
glyph.bounds.size.y = static_cast<float>(bitmap.rows);
glyph.bounds.position = Vector2f(Vector2i(bitmapGlyph->left, -bitmapGlyph->top));
glyph.bounds.size = Vector2f(Vector2u(bitmap.width, bitmap.rows));
// 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* end = current + width * height * 4;
std::uint8_t* end = current + size.x * size.y * 4;
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)
{
// 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
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;
}
pixels += bitmap.pitch;
@ -610,12 +604,12 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
else
{
// 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
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];
}
pixels += bitmap.pitch;
@ -623,11 +617,9 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
}
// Write the pixels to the texture
const unsigned int x = static_cast<unsigned int>(glyph.textureRect.position.x) - padding;
const unsigned int y = static_cast<unsigned int>(glyph.textureRect.position.y) - padding;
const unsigned int w = static_cast<unsigned int>(glyph.textureRect.size.x) + 2 * padding;
const unsigned int h = static_cast<unsigned int>(glyph.textureRect.size.y) + 2 * padding;
page.texture.update(m_pixelBuffer.data(), {w, h}, {x, y});
const auto dest = Vector2u(glyph.textureRect.position) - Vector2u(padding, padding);
const auto updateSize = Vector2u(glyph.textureRect.size) + 2u * Vector2u(padding, padding);
page.texture.update(m_pixelBuffer.data(), updateSize, dest);
}
// Delete the FT glyph

View File

@ -265,15 +265,14 @@ void Shape::updateTexCoords()
{
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)
{
const float xratio = m_insideBounds.size.x > 0
? (m_vertices[i].position.x - m_insideBounds.position.x) / m_insideBounds.size.x
: 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});
const Vector2f ratio = (m_vertices[i].position - m_insideBounds.position).cwiseDiv(safeInsideSize);
m_vertices[i].texCoords = convertedTextureRect.position + convertedTextureRect.size.cwiseMul(ratio);
}
}

View File

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

View File

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