Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion DOM/Sources/Parser.XML.Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,12 @@ extension XMLParser {
var scanner = XMLParser.Scanner(text: value)
return try scanner.scanCoordinate()
}


func parseCoordinateOrPercentage(_ value: String) throws -> DOM.Coordinate {
var scanner = XMLParser.Scanner(text: value)
return try scanner.scanCoordinateOrPercentage()
}

func parseLength(_ value: String) throws -> DOM.Length {
var scanner = XMLParser.Scanner(text: value)
return try scanner.scanLength()
Expand Down
8 changes: 4 additions & 4 deletions DOM/Sources/Parser.XML.LinearGradient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ extension XMLParser {

let nodeAtt: any AttributeParser = try parseAttributes(e)
let node = DOM.LinearGradient(id: try nodeAtt.parseString("id"))
node.x1 = try nodeAtt.parseCoordinate("x1")
node.y1 = try nodeAtt.parseCoordinate("y1")
node.x2 = try nodeAtt.parseCoordinate("x2")
node.y2 = try nodeAtt.parseCoordinate("y2")
node.x1 = try nodeAtt.parseCoordinateOrPercentage("x1")
node.y1 = try nodeAtt.parseCoordinateOrPercentage("y1")
node.x2 = try nodeAtt.parseCoordinateOrPercentage("x2")
node.y2 = try nodeAtt.parseCoordinateOrPercentage("y2")

for n in e.children where n.name == "stop" {
let att: any AttributeParser = try parseAttributes(n)
Expand Down
12 changes: 6 additions & 6 deletions DOM/Sources/Parser.XML.RadialGradient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ extension XMLParser {

let nodeAtt: any AttributeParser = try parseAttributes(e)
let node = DOM.RadialGradient(id: try nodeAtt.parseString("id"))
node.r = try? nodeAtt.parseCoordinate("r")
node.cx = try? nodeAtt.parseCoordinate("cx")
node.cy = try? nodeAtt.parseCoordinate("cy")
node.fr = try? nodeAtt.parseCoordinate("fr")
node.fx = try? nodeAtt.parseCoordinate("fx")
node.fy = try? nodeAtt.parseCoordinate("fy")
node.r = try? nodeAtt.parseCoordinateOrPercentage("r")
node.cx = try? nodeAtt.parseCoordinateOrPercentage("cx")
node.cy = try? nodeAtt.parseCoordinateOrPercentage("cy")
node.fr = try? nodeAtt.parseCoordinateOrPercentage("fr")
node.fx = try? nodeAtt.parseCoordinateOrPercentage("fx")
node.fy = try? nodeAtt.parseCoordinateOrPercentage("fy")

for n in e.children where n.name == "stop" {
let att: any AttributeParser = try parseAttributes(n)
Expand Down
11 changes: 11 additions & 0 deletions DOM/Sources/Parser.XML.Scanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,17 @@ package extension XMLParser {
let unit = scanUnit() ?? .pixel
return DOM.Coordinate(double.apply(unit: unit))
}

package mutating func scanCoordinateOrPercentage() throws -> DOM.Coordinate {
let double = try scanDouble()
scanner.currentIndex = currentIndex
if scanner.scanString("%") != nil {
currentIndex = scanner.currentIndex
return DOM.Coordinate(double / 100.0)
}
let unit = scanUnit() ?? .pixel
return DOM.Coordinate(double.apply(unit: unit))
}

package mutating func scanPercentageFloat() throws -> Float {
scanner.currentIndex = currentIndex
Expand Down
9 changes: 9 additions & 0 deletions DOM/Sources/Parser.XML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ package protocol AttributeValueParser {
func parseFloats(_ value: String) throws -> [DOM.Float]
func parsePercentage(_ value: String) throws -> DOM.Float
func parseCoordinate(_ value: String) throws -> DOM.Coordinate
func parseCoordinateOrPercentage(_ value: String) throws -> DOM.Coordinate
func parseLength(_ value: String) throws -> DOM.Length
func parseBool(_ value: String) throws -> DOM.Bool
func parseFill(_ value: String) throws -> DOM.Fill
Expand Down Expand Up @@ -108,6 +109,10 @@ package extension AttributeParser {
return try parse(key) { return try parser.parseCoordinate($0) }
}

func parseCoordinateOrPercentage(_ key: String) throws -> DOM.Coordinate {
return try parse(key) { return try parser.parseCoordinateOrPercentage($0) }
}

func parseLength(_ key: String) throws -> DOM.Length {
return try parse(key) { return try parser.parseLength($0) }
}
Expand Down Expand Up @@ -187,6 +192,10 @@ package extension AttributeParser {
return try parse(key) { return try parser.parseCoordinate($0) }
}

func parseCoordinateOrPercentage(_ key: String) throws -> DOM.Coordinate? {
return try parse(key) { return try parser.parseCoordinateOrPercentage($0) }
}

func parseLength(_ key: String) throws -> DOM.Length? {
return try parse(key) { return try parser.parseLength($0) }
}
Expand Down
32 changes: 32 additions & 0 deletions DOM/Tests/Parser.XML.LinearGradientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,38 @@ struct ParserXMLLinearGradientTests {
#expect(try XMLParser().parseLinearGradients(parent).count == 3)
}

@Test
func parseCoordinatesWithPercentage() throws {
let element = XML.Element(name: "linearGradient", attributes: [
"id": "a",
"x1": "3.309%",
"y1": "28.41%",
"x2": "103.216%",
"y2": "64.511%"
])
let gradient = try XMLParser().parseLinearGradient(element)
#expect(abs((gradient.x1 ?? 0) - 0.03309) < 0.0001)
#expect(abs((gradient.y1 ?? 0) - 0.2841) < 0.0001)
#expect(abs((gradient.x2 ?? 0) - 1.03216) < 0.0001)
#expect(abs((gradient.y2 ?? 0) - 0.64511) < 0.0001)
}

@Test
func parseCoordinatesWithoutPercentage() throws {
let element = XML.Element(name: "linearGradient", attributes: [
"id": "b",
"x1": "0",
"y1": "0.5",
"x2": "1",
"y2": "0.5"
])
let gradient = try XMLParser().parseLinearGradient(element)
#expect(gradient.x1 == 0)
#expect(gradient.y1 == 0.5)
#expect(gradient.x2 == 1)
#expect(gradient.y2 == 0.5)
}

@Test
func parseFile() throws {
let dom = try DOM.SVG.parse(fileNamed: "linearGradient.svg", in: .test)
Expand Down
17 changes: 17 additions & 0 deletions DOM/Tests/Parser.XML.RadialGradientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ struct ParserXMLRadialGradientTests {
#expect(try XMLParser().parseRadialGradients(parent).count == 3)
}

@Test
func parseCoordinatesWithPercentage() throws {
let element = XML.Element.makeMockGradient()
element.attributes["r"] = "10%"
element.attributes["cx"] = "50%"
element.attributes["cy"] = "25%"
element.attributes["fx"] = "50%"
element.attributes["fy"] = "25%"

let gradient = try XMLParser().parseRadialGradient(element)
#expect(abs((gradient.r ?? 0) - 0.1) < 0.0001)
#expect(abs((gradient.cx ?? 0) - 0.5) < 0.0001)
#expect(abs((gradient.cy ?? 0) - 0.25) < 0.0001)
#expect(abs((gradient.fx ?? 0) - 0.5) < 0.0001)
#expect(abs((gradient.fy ?? 0) - 0.25) < 0.0001)
}

@Test
func parseCoordinates() throws {
let element = XML.Element.makeMockGradient()
Expand Down
Loading