Use svg viewbox

This commit is contained in:
2026-03-11 13:39:47 -06:00
parent 38e044192e
commit 2777ca2a74

View File

@@ -26,18 +26,18 @@ public final class SvgNodeLoader {
}
public static Pane loadSquare(String resourcePath, double size) {
Group content = readSvg(resourcePath);
var bounds = content.getLayoutBounds();
SvgDocument svg = readSvg(resourcePath);
double inset = size * 0.08;
double available = size - (inset * 2);
double scale = Math.min(available / bounds.getWidth(), available / bounds.getHeight());
double scale = Math.min(available / svg.width(), available / svg.height());
content.setScaleX(scale);
content.setScaleY(scale);
content.setLayoutX(inset + ((available - (bounds.getWidth() * scale)) / 2) - (bounds.getMinX() * scale));
content.setLayoutY(inset + ((available - (bounds.getHeight() * scale)) / 2) - (bounds.getMinY() * scale));
Group graphic = svg.content();
graphic.setScaleX(scale);
graphic.setScaleY(scale);
graphic.setLayoutX(inset);
graphic.setLayoutY(inset);
Pane pane = new Pane(content);
Pane pane = new Pane(graphic);
pane.setMinSize(size, size);
pane.setPrefSize(size, size);
pane.setMaxSize(size, size);
@@ -45,16 +45,19 @@ public final class SvgNodeLoader {
return pane;
}
private static Group readSvg(String resourcePath) {
private static SvgDocument readSvg(String resourcePath) {
try (Reader reader = requireResource(resourcePath)) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
Document document = factory.newDocumentBuilder().parse(new InputSource(reader));
Element root = document.getDocumentElement();
double[] viewBox = parseViewBox(root.getAttribute("viewBox"));
Map<String, Map<String, String>> styles = parseStyles(root);
Group content = new Group();
appendChildren(root, content, styles);
return content;
content.setTranslateX(-viewBox[0]);
content.setTranslateY(-viewBox[1]);
return new SvgDocument(content, viewBox[2], viewBox[3]);
} catch (Exception e) {
throw new IllegalStateException("Unable to load SVG: " + resourcePath, e);
}
@@ -68,6 +71,19 @@ public final class SvgNodeLoader {
return new InputStreamReader(stream, StandardCharsets.UTF_8);
}
private static double[] parseViewBox(String viewBox) {
String[] parts = viewBox.trim().split("\\s+");
if (parts.length != 4) {
throw new IllegalArgumentException("Invalid viewBox: " + viewBox);
}
return new double[] {
Double.parseDouble(parts[0]),
Double.parseDouble(parts[1]),
Double.parseDouble(parts[2]),
Double.parseDouble(parts[3])
};
}
private static Map<String, Map<String, String>> parseStyles(Element root) {
Map<String, Map<String, String>> styles = new HashMap<>();
NodeList styleNodes = root.getElementsByTagName("style");
@@ -179,4 +195,7 @@ public final class SvgNodeLoader {
styleMap.put(attribute, value);
}
}
private record SvgDocument(Group content, double width, double height) {
}
}