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
2 changes: 1 addition & 1 deletion Examples/Sources/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ViewController: UIViewController {

override func loadView() {
let imageView = UIImageView(frame: UIScreen.main.bounds)
imageView.image = SVG(named: "rgba.svg", in: .samples)?.rasterize()
imageView.image = SVG(named: "stars.svg", in: .samples)?.rasterize()
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = .white
self.view = imageView
Expand Down
20 changes: 20 additions & 0 deletions Samples.bundle/stars.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion SwiftDraw/LayerTree.Builder.Layer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extension LayerTree.Builder {

func makeUseLayerContents(from use: DOM.Use, with state: State) throws -> LayerTree.Layer.Contents {
guard
let id = use.href.fragment,
let id = use.href.fragmentID,
let element = svg.firstGraphicsElement(with: id) else {
throw LayerTree.Error.invalid("missing referenced element: \(use.href)")
}
Expand Down
20 changes: 10 additions & 10 deletions SwiftDraw/LayerTree.Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@
}

func createClipShapes(for element: DOM.GraphicsElement) -> [Shape] {
guard let clipId = element.attributes.clipPath?.fragment,
guard let clipId = element.attributes.clipPath?.fragmentID,
let clip = svg.defs.clipPaths.first(where: { $0.id == clipId }) else { return [] }

return clip.childElements.compactMap{ Builder.makeShape(from: $0) }
}

func createMaskLayer(for element: DOM.GraphicsElement) -> Layer? {
guard let maskId = element.attributes.mask?.fragment,
guard let maskId = element.attributes.mask?.fragmentID,
let mask = svg.defs.masks.first(where: { $0.id == maskId }) else { return nil }

let l = Layer()
Expand All @@ -145,7 +145,7 @@
}

func makeFilters(for state: State) -> [Filter] {
guard let filterId = state.filter?.fragment,
guard let filterId = state.filter?.fragmentID,
let filter = svg.defs.filters.first(where: { $0.id == filterId }) else { return [] }
return filter.effects
}
Expand Down Expand Up @@ -191,15 +191,15 @@
.withAlpha(state.fillOpacity).maybeNone()

if case .url(let patternId) = state.fill,
let element = svg.defs.patterns.first(where: { $0.id == patternId.fragment }) {
let element = svg.defs.patterns.first(where: { $0.id == patternId.fragmentID }) {
let pattern = makePattern(for: element)
return LayerTree.FillAttributes(pattern: pattern, rule: state.fillRule, opacity: state.fillOpacity)
} else if case .url(let gradientId) = state.fill,
let element = svg.defs.linearGradients.first(where: { $0.id == gradientId.fragment }),
let element = svg.defs.linearGradients.first(where: { $0.id == gradientId.fragmentID }),
let gradient = makeGradient(for: element) {
return LayerTree.FillAttributes(linear: gradient, rule: state.fillRule, opacity: state.fillOpacity)
} else if case .url(let gradientId) = state.fill,
let element = svg.defs.radialGradients.first(where: { $0.id == gradientId.fragment }),
let element = svg.defs.radialGradients.first(where: { $0.id == gradientId.fragmentID }),
let gradient = makeGradient(for: element) {
return LayerTree.FillAttributes(radial: gradient, rule: state.fillRule, opacity: state.fillOpacity)
} else {
Expand All @@ -208,15 +208,15 @@
}

func makeLinearGradient(for gradientId: URL) -> LayerTree.LinearGradient? {
guard let element = svg.defs.linearGradients.first(where: { $0.id == gradientId.fragment }),
guard let element = svg.defs.linearGradients.first(where: { $0.id == gradientId.fragmentID }),

Check warning on line 211 in SwiftDraw/LayerTree.Builder.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/LayerTree.Builder.swift#L211

Added line #L211 was not covered by tests
let gradient = makeGradient(for: element) else {
return nil
}
return gradient
}

func makeRadialGradient(for gradientId: URL) -> LayerTree.RadialGradient? {
guard let element = svg.defs.radialGradients.first(where: { $0.id == gradientId.fragment }),
guard let element = svg.defs.radialGradients.first(where: { $0.id == gradientId.fragmentID }),

Check warning on line 219 in SwiftDraw/LayerTree.Builder.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/LayerTree.Builder.swift#L219

Added line #L219 was not covered by tests
let gradient = makeGradient(for: element) else {
return nil
}
Expand Down Expand Up @@ -249,7 +249,7 @@
let y2 = element.y2 ?? 0

var stops = [LayerTree.Gradient.Stop]()
if let id = element.href?.fragment,
if let id = element.href?.fragmentID,
let reference = svg.defs.linearGradients.first(where: { $0.id == id }) {
stops = makeGradientStops(for: reference)
} else {
Expand All @@ -272,7 +272,7 @@

func makeGradient(for element: DOM.RadialGradient) -> LayerTree.RadialGradient? {
var stops = [LayerTree.Gradient.Stop]()
if let id = element.href?.fragment,
if let id = element.href?.fragmentID,
let reference = svg.defs.radialGradients.first(where: { $0.id == id }) {
stops = makeGradientStops(for: reference)
} else {
Expand Down
48 changes: 48 additions & 0 deletions SwiftDraw/URL+Fragment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// URL+Fragment.swift
// SwiftDraw
//
// Created by Simon Whitty on 12/10/24.
// Copyright 2024 Simon Whitty
//
// Distributed under the permissive zlib license
// Get the latest version from here:
//
// https://github.com/swhitty/SwiftDraw
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//

import Foundation

extension URL {

var fragmentID: String? {
#if compiler(>=5.7) && canImport(Darwin)
if #available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) {
return fragment(percentEncoded: false)
} else {
return fragment

Check warning on line 41 in SwiftDraw/URL+Fragment.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/URL+Fragment.swift#L41

Added line #L41 was not covered by tests
}
#else
return fragment
#endif

Check warning on line 45 in SwiftDraw/URL+Fragment.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/URL+Fragment.swift#L43-L45

Added lines #L43 - L45 were not covered by tests
}

}
8 changes: 4 additions & 4 deletions SwiftDrawTests/Parser.GraphicAttributeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ final class ParserGraphicAttributeTests: XCTestCase {
XCTAssertEqual(parsed.fillOpacity, 0.25)
XCTAssertEqual(parsed.fillRule, .evenodd)
XCTAssertEqual(parsed.transform!, [.scale(sx: 15, sy: 15)])
XCTAssertEqual(parsed.clipPath?.fragment, "circlePath")
XCTAssertEqual(parsed.mask?.fragment, "fancyMask")
XCTAssertEqual(parsed.filter?.fragment, "blur")
XCTAssertEqual(parsed.clipPath?.fragmentID, "circlePath")
XCTAssertEqual(parsed.mask?.fragmentID, "fancyMask")
XCTAssertEqual(parsed.filter?.fragmentID, "blur")
}

func testCircle() throws {
Expand All @@ -93,7 +93,7 @@ final class ParserGraphicAttributeTests: XCTestCase {
let parsed = try XMLParser().parseGraphicsElement(el)
let circle = parsed as? DOM.Circle
XCTAssertNotNil(circle)
XCTAssertEqual(circle?.style.clipPath?.fragment, "cp1")
XCTAssertEqual(circle?.style.clipPath?.fragmentID, "cp1")
XCTAssertEqual(circle?.style.fill, .color(.keyword(.black)))
XCTAssertEqual(circle?.style.strokeWidth, 2)
}
Expand Down
4 changes: 2 additions & 2 deletions SwiftDrawTests/UseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ final class UseTests: XCTestCase {
var node = ["xlink:href": "#line2", "href": "#line1"]

var parsed = try XMLParser().parseUse(node)
XCTAssertEqual(parsed.href.fragment, "line2")
XCTAssertEqual(parsed.href.fragmentID, "line2")
XCTAssertNil(parsed.x)
XCTAssertNil(parsed.y)

node["x"] = "20"
node["y"] = "30"

parsed = try XMLParser().parseUse(node)
XCTAssertEqual(parsed.href.fragment, "line2")
XCTAssertEqual(parsed.href.fragmentID, "line2")
XCTAssertEqual(parsed.x, 20)
XCTAssertEqual(parsed.y, 30)
}
Expand Down
11 changes: 6 additions & 5 deletions SwiftDrawTests/ValueParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,16 @@ final class ValueParserTests: XCTestCase {
}

func testUrl() {
XCTAssertEqual(try parser.parseUrl("#testingId").fragment, "testingId")
#if compiler(>=5.9) && canImport(Darwin)
XCTAssertEqual(try parser.parseUrl("#testing🐟").fragmentID, "testing🐟")
#else
XCTAssertEqual(try parser.parseUrl("#testing").fragmentID, "testing")
#endif
XCTAssertEqual(try parser.parseUrl("http://www.google.com").host, "www.google.com")

//XCTAssertThrowsError(try parser.parseUrl("www.google.com"))
//XCTAssertThrowsError(try parser.parseUrl("sd"))
}

func testUrlSelector() {
XCTAssertEqual(try parser.parseUrlSelector("url(#testingId)").fragment, "testingId")
XCTAssertEqual(try parser.parseUrlSelector("url(#testingId)").fragmentID, "testingId")
XCTAssertEqual(try parser.parseUrlSelector("url(http://www.google.com)").host, "www.google.com")

XCTAssertThrowsError(try parser.parseUrlSelector("url(#testingId) other"))
Expand Down