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
47 changes: 47 additions & 0 deletions SwiftDraw/DOM.SVG+Parse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// DOM.SVG+Parse.swift
// SwiftDraw
//
// Created by Simon Whitty on 23/2/25.
// Copyright 2025 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 DOM.SVG {

static func parse(fileURL url: URL, options: XMLParser.Options = .skipInvalidElements) throws -> DOM.SVG {
let element = try XML.SAXParser.parse(contentsOf: url)
let parser = XMLParser(options: options, filename: url.lastPathComponent)
return try parser.parseSVG(element)
}

static func parse(data: Data, options: XMLParser.Options = .skipInvalidElements) throws -> DOM.SVG {
let element = try XML.SAXParser.parse(data: data)
let parser = XMLParser(options: options)
return try parser.parseSVG(element)
}
}
59 changes: 59 additions & 0 deletions SwiftDraw/SVG+Insets.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// SVG+Insets.swift
// SwiftDraw
//
// Created by Simon Whitty on 23/2/25.
// Copyright 2025 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

#if canImport(CoreGraphics)
import CoreGraphics
#endif

public extension SVG {
struct Insets: Equatable {
public var top: CGFloat
public var left: CGFloat
public var bottom: CGFloat
public var right: CGFloat

public init(
top: CGFloat = 0,
left: CGFloat = 0,
bottom: CGFloat = 0,
right: CGFloat = 0
) {
self.top = top
self.left = left
self.bottom = bottom
self.right = right
}

public static let zero = Insets(top: 0, left: 0, bottom: 0, right: 0)
}
}
128 changes: 45 additions & 83 deletions SwiftDraw/SVG.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,56 @@
#if canImport(CoreGraphics)
import CoreGraphics

@objc(SVGImage)
public final class SVG: NSObject {
public struct SVG {
public let size: CGSize

//An Image is simply an array of CoreGraphics draw commands
//see: Renderer.swift
let commands: [RendererCommand<CGTypes>]

public init?(fileURL url: URL, options: SVG.Options = .default) {
do {
let svg = try DOM.SVG.parse(fileURL: url)
self.init(dom: svg, options: options)
} catch {
XMLParser.logParsingError(for: error, filename: url.lastPathComponent, parsing: nil)
return nil

Check warning on line 50 in SwiftDraw/SVG.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/SVG.swift#L49-L50

Added lines #L49 - L50 were not covered by tests
}
}

public init?(named name: String, in bundle: Bundle = Bundle.main, options: SVG.Options = .default) {
guard let url = bundle.url(forResource: name, withExtension: nil) else {
return nil
}

self.init(fileURL: url, options: options)
}

public init?(data: Data, options: SVG.Options = .default) {
guard let svg = try? DOM.SVG.parse(data: data) else {
return nil
}

self.init(dom: svg, options: options)
}

Check warning on line 68 in SwiftDraw/SVG.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/SVG.swift#L62-L68

Added lines #L62 - L68 were not covered by tests

public struct Options: OptionSet {
public let rawValue: Int
public init(rawValue: Int) {
self.rawValue = rawValue
}

public static let hideUnsupportedFilters = Options(rawValue: 1 << 0)

public static let `default`: Options = []
}
}

@available(*, unavailable, renamed: "SVG")
public enum Image { }

extension SVG {

init(dom: DOM.SVG, options: Options) {
self.size = CGSize(width: dom.width, height: dom.height)

Expand All @@ -60,25 +102,11 @@
generator.renderCommands(for: layer)
)
}

public struct Options: OptionSet {
public let rawValue: Int
public init(rawValue: Int) {
self.rawValue = rawValue
}

public static let hideUnsupportedFilters = Options(rawValue: 1 << 0)

public static let `default`: Options = []
}
}

@available(*, unavailable, renamed: "SVG")
public enum Image { }

#else

public final class SVG: NSObject {
public struct SVG {
public let size: CGSize

init(dom: DOM.SVG, options: Options) {
Expand Down Expand Up @@ -116,69 +144,3 @@
}
}
#endif

extension DOM.SVG {

static func parse(fileURL url: URL, options: XMLParser.Options = .skipInvalidElements) throws -> DOM.SVG {
let element = try XML.SAXParser.parse(contentsOf: url)
let parser = XMLParser(options: options, filename: url.lastPathComponent)
return try parser.parseSVG(element)
}

static func parse(data: Data, options: XMLParser.Options = .skipInvalidElements) throws -> DOM.SVG {
let element = try XML.SAXParser.parse(data: data)
let parser = XMLParser(options: options)
return try parser.parseSVG(element)
}
}

public extension SVG {

convenience init?(fileURL url: URL, options: SVG.Options = .default) {
do {
let svg = try DOM.SVG.parse(fileURL: url)
self.init(dom: svg, options: options)
} catch {
XMLParser.logParsingError(for: error, filename: url.lastPathComponent, parsing: nil)
return nil
}
}

convenience init?(named name: String, in bundle: Bundle = Bundle.main, options: SVG.Options = .default) {
guard let url = bundle.url(forResource: name, withExtension: nil) else {
return nil
}

self.init(fileURL: url, options: options)
}

convenience init?(data: Data, options: SVG.Options = .default) {
guard let svg = try? DOM.SVG.parse(data: data) else {
return nil
}

self.init(dom: svg, options: options)
}


struct Insets: Equatable {
public var top: CGFloat
public var left: CGFloat
public var bottom: CGFloat
public var right: CGFloat

public init(
top: CGFloat = 0,
left: CGFloat = 0,
bottom: CGFloat = 0,
right: CGFloat = 0
) {
self.top = top
self.left = left
self.bottom = bottom
self.right = right
}

public static let zero = Insets(top: 0, left: 0, bottom: 0, right: 0)
}
}
5 changes: 2 additions & 3 deletions SwiftDrawTests/SVGTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import XCTest
@testable import SwiftDraw

#if canImport(CoreGraphics)
final class SVGTests: XCTestCase {

func testValidSVGLoads() {
Expand All @@ -46,7 +47,6 @@ final class SVGTests: XCTestCase {
XCTAssertNil(SVG(named: "missing.svg", in: .test))
}

#if canImport(CoreGraphics)
func testImageRasterizes() {
let image = SVG.makeLines()
let rendered = image.rasterize(scale: 1)
Expand All @@ -71,7 +71,6 @@ final class SVGTests: XCTestCase {
XCTAssertNoThrow(try image.jpegData())
XCTAssertNoThrow(try image.pdfData())
}
#endif

#if canImport(UIKit)
func testRasterize() {
Expand All @@ -86,7 +85,6 @@ final class SVGTests: XCTestCase {
XCTAssertEqual(reloaded.scale, 1)
}
#endif

}

private extension SVG {
Expand All @@ -98,3 +96,4 @@ private extension SVG {
return SVG(dom: svg, options: .default)
}
}
#endif
4 changes: 2 additions & 2 deletions SwiftDrawTests/UIImage+ImageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ final class UIImageTests: XCTestCase {
}
}

#endif

private extension SVG {

static func parse(_ code: String) throws -> SVG {
Expand All @@ -90,3 +88,5 @@ private extension SVG {
var errorDescription: String? = "Invalid SVG"
}
}

#endif