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
80 changes: 80 additions & 0 deletions SwiftDraw/Sources/CanvasNSView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// CanvasNSView.swift
// SwiftDraw
//
// Created by Simon Whitty on 07/9/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.
//

#if canImport(AppKit)
import AppKit
import SwiftUI

@available(macOS, deprecated: 12.0, message: "use SwiftUI.Canvas")
struct CanvasFallbackView: NSViewRepresentable {

var svg: SVG
var capInsets: EdgeInsets
var resizingMode: SVGView.ResizingMode

func makeNSView(context: Context) -> CanvasNSView {
let nsView = CanvasNSView()
nsView.wantsLayer = true
nsView.layerContentsRedrawPolicy = .duringViewResize
nsView.layer?.needsDisplayOnBoundsChange = true
return nsView
}

func updateNSView(_ nsView: CanvasNSView, context: Context) {
nsView.svg = svg
nsView.resizeMode = resizingMode
nsView.capInsets = (capInsets.top, capInsets.leading, capInsets.bottom, capInsets.trailing)
nsView.needsDisplay = true
}
}

final class CanvasNSView: NSView {

var svg: SVG?
var resizeMode: SVGView.ResizingMode = .stretch
var capInsets: (top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) = (0, 0, 0, 0)

override var isFlipped: Bool { true }

override func draw(_ dirtyRect: NSRect) {
guard let svg,
let ctx = NSGraphicsContext.current?.cgContext else { return }

ctx.draw(
svg,
in: bounds,
capInsets: capInsets,
byTiling: resizeMode == .tile
)
}
}

#endif
77 changes: 77 additions & 0 deletions SwiftDraw/Sources/CanvasUIView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// CanvasUIView.swift
// SwiftDraw
//
// Created by Simon Whitty on 07/9/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.
//

#if canImport(UIKit)
import UIKit
import SwiftUI

@available(iOS, deprecated: 15.0, message: "use SwiftUI.Canvas")
struct CanvasFallbackView: UIViewRepresentable {

var svg: SVG
var capInsets: EdgeInsets
var resizingMode: SVGView.ResizingMode

func makeUIView(context: Context) -> CanvasUIView {
let uiView = CanvasUIView()
uiView.isOpaque = false
uiView.contentMode = .redraw
return uiView
}

func updateUIView(_ uiView: CanvasUIView, context: Context) {
uiView.svg = svg
uiView.resizeMode = resizingMode
uiView.capInsets = (capInsets.top, capInsets.leading, capInsets.bottom, capInsets.trailing)
uiView.setNeedsDisplay()
}
}

final class CanvasUIView: UIView {

var svg: SVG?
var resizeMode: SVGView.ResizingMode = .stretch
var capInsets: (top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) = (0, 0, 0, 0)

override func draw(_ rect: CGRect) {
guard let svg,
let ctx = UIGraphicsGetCurrentContext() else { return }

ctx.draw(
svg,
in: rect,
capInsets: capInsets,
byTiling: resizeMode == .tile
)
}
}

#endif
28 changes: 18 additions & 10 deletions SwiftDraw/Sources/SVGView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#if canImport(SwiftUI)
public import SwiftUI

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public struct SVGView: View {

public init(_ name: String, bundle: Bundle = .main) {
Expand Down Expand Up @@ -83,17 +82,26 @@ public struct SVGView: View {
return copy
}

@ViewBuilder
private static func makeCanvas(svg: SVG, capInsets: EdgeInsets = .init(), resizingMode: ResizingMode) -> some View {
Canvas(
opaque: false,
colorMode: .linear,
rendersAsynchronously: false
) { ctx, size in
ctx.draw(
svg,
in: CGRect(origin: .zero, size: size),
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
Canvas(
opaque: false,
colorMode: .linear,
rendersAsynchronously: false
) { ctx, size in
ctx.draw(
svg,
in: CGRect(origin: .zero, size: size),
capInsets: capInsets,
byTiling: resizingMode == .tile
)
}
} else {
CanvasFallbackView(
svg: svg,
capInsets: capInsets,
byTiling: resizingMode == .tile
resizingMode: resizingMode
)
}
}
Expand Down