From 4ac7c60d076006a3ab78cdd46cdf0218d8643bce Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 27 Sep 2026 16:46:17 +0200 Subject: [PATCH] Add rounded borders to RenderScope drawRoundedBorder draws an outline inset into the given bounds so it lines up with a rounded rectangle of the same size and radius, and a new drawRoundedRectangle overload draws both with separate background and border colors. Both shapes share one SVG-to-texture helper. Co-Authored-By: Claude Opus 5.5 --- .../java/org/saturnclient/ui/RenderScope.java | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/saturnclient/ui/RenderScope.java b/src/main/java/org/saturnclient/ui/RenderScope.java index ed4513f..0bbc677 100644 --- a/src/main/java/org/saturnclient/ui/RenderScope.java +++ b/src/main/java/org/saturnclient/ui/RenderScope.java @@ -3,6 +3,7 @@ package org.saturnclient.ui; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Locale; import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.SpriteRef; @@ -36,19 +37,66 @@ public interface RenderScope { radius = Math.min(radius, width / 2); radius = Math.min(radius, height / 2); - String svg = String.format( - "" + - "" + - "", - width, height, + String rect = String.format( + "", width, height, radius, radius); + drawSvgShape(rect, "rounded_" + width + "_" + height + "_" + radius, x, y, width, height, color); + } + + /** + * Draws a rounded outline that stays inside the given bounds, so it lines up + * with a {@link #drawRoundedRectangle} of the same size and radius. + */ + default void drawRoundedBorder(int x, int y, int width, int height, int radius, int thickness, int color) { + if (color == 0 || thickness <= 0) + return; + + radius = Math.min(radius, width / 2); + radius = Math.min(radius, height / 2); + thickness = Math.min(thickness, Math.min(width, height) / 2); + + // The stroke is centered on the path, so inset it by half its width. + float inset = thickness / 2f; + float innerRadius = Math.max(0, radius - inset); + + String rect = String.format(Locale.ROOT, + "", + inset, inset, + width - (float) thickness, height - (float) thickness, + innerRadius, innerRadius, + thickness); + + drawSvgShape(rect, "rounded_border_" + width + "_" + height + "_" + radius + "_" + thickness, + x, y, width, height, color); + } + + /** + * Draws a rounded rectangle filled with {@code background} and outlined with + * {@code border}. Either color can be 0 to skip that part. + */ + default void drawRoundedRectangle(int x, int y, int width, int height, int radius, int thickness, + int background, int border) { + drawRoundedRectangle(x, y, width, height, radius, background); + drawRoundedBorder(x, y, width, height, radius, thickness, border); + } + + /** + * Renders {@code shape} (SVG elements in a {@code width} x {@code height} + * canvas, drawn in white) to a cached texture and draws it tinted with + * {@code color}. + */ + private void drawSvgShape(String shape, String cacheKey, int x, int y, int width, int height, int color) { + String svg = String.format( + "%s", + width, height, shape); + InputStream svgStream = new ByteArrayInputStream(svg.getBytes(StandardCharsets.UTF_8)); drawTexture(SvgTexture.getSvg(svgStream, - IdentifierRef.ofSaturn( - "textures/gui/tmp_rect/rounded_" + width + "_" + height + "_" + radius), + IdentifierRef.ofSaturn("textures/gui/tmp_rect/" + cacheKey), width * 4, height * 4), x, y, 0, 0, width, height, color); }