From b6bd4c6bf6c0bf02cfc79ef80fb64925c5f70356 Mon Sep 17 00:00:00 2001 From: Iryna Date: Tue, 29 Sep 2026 20:08:19 +0200 Subject: [PATCH] Fix fractional SVG dimensions --- DOM/Sources/DOM.SVG.swift | 6 +++--- DOM/Sources/Parser.XML.SVG.swift | 2 +- DOM/Tests/Parser.SVGTests.swift | 12 ++++++++++-- SwiftDraw/Sources/Formatter/XML.Formatter.SVG.swift | 4 ++-- SwiftDraw/Sources/LayerTree/LayerTree.Builder.swift | 4 ++-- SwiftDraw/Sources/SVG.swift | 3 +-- .../Tests/LayerTree/LayerTree.BuilderTests.swift | 4 ++-- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/DOM/Sources/DOM.SVG.swift b/DOM/Sources/DOM.SVG.swift index c551ca9a..7852c3b0 100644 --- a/DOM/Sources/DOM.SVG.swift +++ b/DOM/Sources/DOM.SVG.swift @@ -33,8 +33,8 @@ package extension DOM { final class SVG: GraphicsElement, ContainerElement { package var x: Coordinate? package var y: Coordinate? - package var width: Length - package var height: Length + package var width: Coordinate + package var height: Coordinate package var viewBox: ViewBox? package var childElements = [GraphicsElement]() @@ -42,7 +42,7 @@ package extension DOM { package var styles = [StyleSheet]() package var defs = Defs() - package init(x: Coordinate? = nil, y: Coordinate? = nil, width: Length, height: Length) { + package init(x: Coordinate? = nil, y: Coordinate? = nil, width: Coordinate, height: Coordinate) { self.x = x self.y = y self.width = width diff --git a/DOM/Sources/Parser.XML.SVG.swift b/DOM/Sources/Parser.XML.SVG.swift index 4d76207c..f99a7dba 100644 --- a/DOM/Sources/Parser.XML.SVG.swift +++ b/DOM/Sources/Parser.XML.SVG.swift @@ -56,7 +56,7 @@ package extension XMLParser { throw XMLParser.Error.unresolvableDimension(reason: makeUnresolvedReason(attribute: "height", raw: heightRaw, hasViewBox: viewBox != nil)) } - let svg = DOM.SVG(width: DOM.Length(w), height: DOM.Length(h)) + let svg = DOM.SVG(width: w, height: h) svg.x = try att.parseCoordinate("x") svg.y = try att.parseCoordinate("y") svg.childElements = try parseGraphicsElements(e.children) diff --git a/DOM/Tests/Parser.SVGTests.swift b/DOM/Tests/Parser.SVGTests.swift index 13c017f9..d83fae20 100644 --- a/DOM/Tests/Parser.SVGTests.swift +++ b/DOM/Tests/Parser.SVGTests.swift @@ -56,14 +56,22 @@ struct ParserSVGTests { #expect(parsed != expected2) } + @Test + func svgWithFractionalDimensions() throws { + let node = XML.Element(name: "svg", attributes: ["width": "5.8", "height": "5.8"]) + let parser = DOMXMLParser() + let parsed = try parser.parseSVG(node) + #expect(Float(parsed.width) == 5.8) + #expect(Float(parsed.height) == 5.8) + } @Test func svgWithUnits() throws { let node = XML.Element(name: "svg", attributes: ["width": "10cm", "height": "2in"]) let parser = DOMXMLParser() let parsed = try parser.parseSVG(node) - // 10cm = 10 * 37.795 = 377.95 → truncated to 377 - #expect(parsed.width == 377) + // 10cm = 10 * 37.795 = 377.95 + #expect(parsed.width == 377.95) // 2in = 2 * 96 = 192 #expect(parsed.height == 192) } diff --git a/SwiftDraw/Sources/Formatter/XML.Formatter.SVG.swift b/SwiftDraw/Sources/Formatter/XML.Formatter.SVG.swift index 3dbe534e..ae9531ec 100644 --- a/SwiftDraw/Sources/Formatter/XML.Formatter.SVG.swift +++ b/SwiftDraw/Sources/Formatter/XML.Formatter.SVG.swift @@ -57,8 +57,8 @@ extension XML.Formatter { element.attributes["viewBox"] = makeViewBox(svg.viewBox) if svg.viewBox != .init(x: 0, y: 0, width: DOM.Coordinate(svg.width), height: DOM.Coordinate(svg.height)) { - element.attributes["width"] = formatter.formatLength(svg.width) - element.attributes["height"] = formatter.formatLength(svg.height) + element.attributes["width"] = formatter.format(svg.width) + element.attributes["height"] = formatter.format(svg.height) } try element.children.append(contentsOf: makeStyles(svg.styles)) diff --git a/SwiftDraw/Sources/LayerTree/LayerTree.Builder.swift b/SwiftDraw/Sources/LayerTree/LayerTree.Builder.swift index ca9ae1c8..d80845b0 100644 --- a/SwiftDraw/Sources/LayerTree/LayerTree.Builder.swift +++ b/SwiftDraw/Sources/LayerTree/LayerTree.Builder.swift @@ -64,8 +64,8 @@ extension LayerTree { x: DOM.Coordinate?, y: DOM.Coordinate?, viewBox: DOM.SVG.ViewBox?, - width: DOM.Length, - height: DOM.Length + width: DOM.Coordinate, + height: DOM.Coordinate ) -> [LayerTree.Transform] { let position = LayerTree.Transform.translate(tx: x ?? 0, ty: y ?? 0) let viewBox = viewBox ?? DOM.SVG.ViewBox(x: 0, y: 0, width: .init(width), height: .init(height)) diff --git a/SwiftDraw/Sources/SVG.swift b/SwiftDraw/Sources/SVG.swift index b4a23240..8fc8a1b6 100644 --- a/SwiftDraw/Sources/SVG.swift +++ b/SwiftDraw/Sources/SVG.swift @@ -160,8 +160,7 @@ extension SVG { } init(dom: DOM.SVG, options: Options) { - self.size = CGSize(width: dom.width, height: dom.height) - + self.size = CGSize(width: CGFloat(dom.width), height: CGFloat(dom.height)) //To create the draw commands; // - XML is parsed into DOM.SVG // - DOM.SVG is converted into a LayerTree diff --git a/SwiftDraw/Tests/LayerTree/LayerTree.BuilderTests.swift b/SwiftDraw/Tests/LayerTree/LayerTree.BuilderTests.swift index 3c041bab..a29a85e1 100644 --- a/SwiftDraw/Tests/LayerTree/LayerTree.BuilderTests.swift +++ b/SwiftDraw/Tests/LayerTree/LayerTree.BuilderTests.swift @@ -202,8 +202,8 @@ extension LayerTree.Builder { static func makeTransform( viewBox: DOM.SVG.ViewBox?, - width: DOM.Length, - height: DOM.Length + width: DOM.Coordinate, + height: DOM.Coordinate ) -> [LayerTree.Transform] { makeTransform( x: nil,