Port over SDL_RenderFIllRoundedRect from SDL3 renderer.

This commit is contained in:
Stephen T 2025-01-31 02:35:12 -06:00 committed by Nic Barker
parent ddc20bc8f6
commit 4729bd0fa8

View File

@ -33,6 +33,112 @@ static Clay_Dimensions SDL2_MeasureText(Clay_StringSlice text, Clay_TextElementC
};
}
/* Global for convenience. Even in 4K this is enough for smooth curves (low radius or rect size coupled with
* no AA or low resolution might make it appear as jagged curves) */
static int NUM_CIRCLE_SEGMENTS = 16;
//all rendering is performed by a single SDL call, avoiding multiple RenderRect + plumbing choice for circles.
static void SDL_RenderFillRoundedRect(SDL_Renderer* renderer, const SDL_FRect rect, const float cornerRadius, const Clay_Color _color) {
const SDL_Color color = { (Uint8)(_color.r), (Uint8)(_color.g), (Uint8)(_color.b), (Uint8)(_color.a), };
int indexCount = 0, vertexCount = 0;
const float minRadius = SDL_min(rect.w, rect.h) / 2.0f;
const float clampedRadius = SDL_min(cornerRadius, minRadius);
const int numCircleSegments = SDL_max(NUM_CIRCLE_SEGMENTS, (int)clampedRadius * 0.5f);
int totalVertices = 4 + (4 * (numCircleSegments * 2)) + 2 * 4;
int totalIndices = 6 + (4 * (numCircleSegments * 3)) + 6 * 4;
SDL_Vertex vertices[totalVertices];
int indices[totalIndices];
//define center rectangle
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + clampedRadius, rect.y + clampedRadius}, color, {0, 0} }; //0 center TL
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w - clampedRadius, rect.y + clampedRadius}, color, {1, 0} }; //1 center TR
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w - clampedRadius, rect.y + rect.h - clampedRadius}, color, {1, 1} }; //2 center BR
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + clampedRadius, rect.y + rect.h - clampedRadius}, color, {0, 1} }; //3 center BL
indices[indexCount++] = 0;
indices[indexCount++] = 1;
indices[indexCount++] = 3;
indices[indexCount++] = 1;
indices[indexCount++] = 2;
indices[indexCount++] = 3;
//define rounded corners as triangle fans
const float step = (M_PI / 2) / numCircleSegments;
for (int i = 0; i < numCircleSegments; i++) {
const float angle1 = (float)i * step;
const float angle2 = ((float)i + 1.0f) * step;
for (int j = 0; j < 4; j++) { // Iterate over four corners
float cx, cy, signX, signY;
switch (j) {
case 0: cx = rect.x + clampedRadius; cy = rect.y + clampedRadius; signX = -1; signY = -1; break; // Top-left
case 1: cx = rect.x + rect.w - clampedRadius; cy = rect.y + clampedRadius; signX = 1; signY = -1; break; // Top-right
case 2: cx = rect.x + rect.w - clampedRadius; cy = rect.y + rect.h - clampedRadius; signX = 1; signY = 1; break; // Bottom-right
case 3: cx = rect.x + clampedRadius; cy = rect.y + rect.h - clampedRadius; signX = -1; signY = 1; break; // Bottom-left
default: return;
}
vertices[vertexCount++] = (SDL_Vertex){ {cx + SDL_cosf(angle1) * clampedRadius * signX, cy + SDL_sinf(angle1) * clampedRadius * signY}, color, {0, 0} };
vertices[vertexCount++] = (SDL_Vertex){ {cx + SDL_cosf(angle2) * clampedRadius * signX, cy + SDL_sinf(angle2) * clampedRadius * signY}, color, {0, 0} };
indices[indexCount++] = j; // Connect to corresponding central rectangle vertex
indices[indexCount++] = vertexCount - 2;
indices[indexCount++] = vertexCount - 1;
}
}
//Define edge rectangles
// Top edge
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + clampedRadius, rect.y}, color, {0, 0} }; //TL
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w - clampedRadius, rect.y}, color, {1, 0} }; //TR
indices[indexCount++] = 0;
indices[indexCount++] = vertexCount - 2; //TL
indices[indexCount++] = vertexCount - 1; //TR
indices[indexCount++] = 1;
indices[indexCount++] = 0;
indices[indexCount++] = vertexCount - 1; //TR
// Right edge
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w, rect.y + clampedRadius}, color, {1, 0} }; //RT
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w, rect.y + rect.h - clampedRadius}, color, {1, 1} }; //RB
indices[indexCount++] = 1;
indices[indexCount++] = vertexCount - 2; //RT
indices[indexCount++] = vertexCount - 1; //RB
indices[indexCount++] = 2;
indices[indexCount++] = 1;
indices[indexCount++] = vertexCount - 1; //RB
// Bottom edge
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + rect.w - clampedRadius, rect.y + rect.h}, color, {1, 1} }; //BR
vertices[vertexCount++] = (SDL_Vertex){ {rect.x + clampedRadius, rect.y + rect.h}, color, {0, 1} }; //BL
indices[indexCount++] = 2;
indices[indexCount++] = vertexCount - 2; //BR
indices[indexCount++] = vertexCount - 1; //BL
indices[indexCount++] = 3;
indices[indexCount++] = 2;
indices[indexCount++] = vertexCount - 1; //BL
// Left edge
vertices[vertexCount++] = (SDL_Vertex){ {rect.x, rect.y + rect.h - clampedRadius}, color, {0, 1} }; //LB
vertices[vertexCount++] = (SDL_Vertex){ {rect.x, rect.y + clampedRadius}, color, {0, 0} }; //LT
indices[indexCount++] = 3;
indices[indexCount++] = vertexCount - 2; //LB
indices[indexCount++] = vertexCount - 1; //LT
indices[indexCount++] = 0;
indices[indexCount++] = 3;
indices[indexCount++] = vertexCount - 1; //LT
// Render everything
SDL_RenderGeometry(renderer, NULL, vertices, vertexCount, indices, indexCount);
}
SDL_Rect currentClippingRectangle;
static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray renderCommands, SDL2_Font *fonts)
@ -53,7 +159,12 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
.w = boundingBox.width,
.h = boundingBox.height,
};
SDL_RenderFillRectF(renderer, &rect);
if (config->cornerRadius.topLeft > 0) {
SDL_RenderFillRoundedRect(renderer, rect, config->cornerRadius.topLeft, color);
}
else {
SDL_RenderFillRectF(renderer, &rect);
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_TEXT: {