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) { public static Pane loadSquare(String resourcePath, double size) {
Group content = readSvg(resourcePath); SvgDocument svg = readSvg(resourcePath);
var bounds = content.getLayoutBounds();
double inset = size * 0.08; double inset = size * 0.08;
double available = size - (inset * 2); 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); Group graphic = svg.content();
content.setScaleY(scale); graphic.setScaleX(scale);
content.setLayoutX(inset + ((available - (bounds.getWidth() * scale)) / 2) - (bounds.getMinX() * scale)); graphic.setScaleY(scale);
content.setLayoutY(inset + ((available - (bounds.getHeight() * scale)) / 2) - (bounds.getMinY() * scale)); graphic.setLayoutX(inset);
graphic.setLayoutY(inset);
Pane pane = new Pane(content); Pane pane = new Pane(graphic);
pane.setMinSize(size, size); pane.setMinSize(size, size);
pane.setPrefSize(size, size); pane.setPrefSize(size, size);
pane.setMaxSize(size, size); pane.setMaxSize(size, size);
@@ -45,16 +45,19 @@ public final class SvgNodeLoader {
return pane; return pane;
} }
private static Group readSvg(String resourcePath) { private static SvgDocument readSvg(String resourcePath) {
try (Reader reader = requireResource(resourcePath)) { try (Reader reader = requireResource(resourcePath)) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false); factory.setNamespaceAware(false);
Document document = factory.newDocumentBuilder().parse(new InputSource(reader)); Document document = factory.newDocumentBuilder().parse(new InputSource(reader));
Element root = document.getDocumentElement(); Element root = document.getDocumentElement();
double[] viewBox = parseViewBox(root.getAttribute("viewBox"));
Map<String, Map<String, String>> styles = parseStyles(root); Map<String, Map<String, String>> styles = parseStyles(root);
Group content = new Group(); Group content = new Group();
appendChildren(root, content, styles); 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) { } catch (Exception e) {
throw new IllegalStateException("Unable to load SVG: " + resourcePath, 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); 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) { private static Map<String, Map<String, String>> parseStyles(Element root) {
Map<String, Map<String, String>> styles = new HashMap<>(); Map<String, Map<String, String>> styles = new HashMap<>();
NodeList styleNodes = root.getElementsByTagName("style"); NodeList styleNodes = root.getElementsByTagName("style");
@@ -179,4 +195,7 @@ public final class SvgNodeLoader {
styleMap.put(attribute, value); styleMap.put(attribute, value);
} }
} }
private record SvgDocument(Group content, double width, double height) {
}
} }