Skip to content

Commit

Permalink
Bevel shape outline corners beyond threshold
Browse files Browse the repository at this point in the history
Inspired by stroke-miterlimit SVG attribute.
  • Loading branch information
kimci86 committed Oct 21, 2023
1 parent c5be658 commit 96b7ccd
Showing 1 changed file with 22 additions and 9 deletions.
31 changes: 22 additions & 9 deletions src/SFML/Graphics/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,10 @@ void Shape::updateOutline()
}

const std::size_t count = m_vertices.getVertexCount() - 2;
m_outlineVertices.resize((count + 1) * 2);
m_outlineVertices.resize((count + 1) * 2); // We need at least that many vertices.
// We will add two more vertices each time we need a bevel.

std::size_t outlineIndex = 0;
for (std::size_t i = 0; i < count; ++i)
{
const std::size_t index = i + 1;
Expand All @@ -313,18 +315,29 @@ void Shape::updateOutline()
if (n2.dot(m_vertices[0].position - p1) > 0)
n2 = -n2;

// Combine them to get the extrusion direction
const float factor = 1.f + (n1.x * n2.x + n1.y * n2.y);
const Vector2f normal = (n1 + n2) / factor;

// Update the outline points
m_outlineVertices[i * 2 + 0].position = p1;
m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness;
const float factor = 1.f + n1.dot(n2);
constexpr float miterLimit = 4.f;
if (miterLimit * miterLimit * factor < 2.f) // Note this is true if factor is 0
{
// The limit on the ratio of the miter length to the outline width is exceeded so add a bevel
m_outlineVertices.resize(m_outlineVertices.getVertexCount() + 2);
m_outlineVertices[outlineIndex++].position = p1;
m_outlineVertices[outlineIndex++].position = p1 + n1 * m_outlineThickness;
m_outlineVertices[outlineIndex++].position = p1;
m_outlineVertices[outlineIndex++].position = p1 + n2 * m_outlineThickness;
}
else
{
const Vector2f extrusion = (n1 + n2) / factor;
m_outlineVertices[outlineIndex++].position = p1;
m_outlineVertices[outlineIndex++].position = p1 + extrusion * m_outlineThickness;
}
}

// Duplicate the first point at the end, to close the outline
m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position;
m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position;
m_outlineVertices[outlineIndex++].position = m_outlineVertices[0].position;
m_outlineVertices[outlineIndex++].position = m_outlineVertices[1].position;

// Update outline colors
updateOutlineColors();
Expand Down

0 comments on commit 96b7ccd

Please sign in to comment.