-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial Commit
- Loading branch information
Showing
10 changed files
with
279 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,22 @@ | ||
# ResizableVector | ||
|
||
A description of this package. | ||
A cross-platform SwiftUI View that resizes images using Cocoa or UIKit. | ||
|
||
This solves an existing SwiftUI Image View issue where vector images have artifacts when significantly scaled. | ||
|
||
Link to related issues: | ||
https://stackoverflow.com/questions/61164005/why-do-pdfs-resized-in-swiftui-getting-sharp-edges | ||
https://stackoverflow.com/questions/57969823/xcode-11-pdf-image-assets-preserve-vector-data-not-working-in-swiftui | ||
|
||
## Installation | ||
|
||
To add ResizableVector to your Xcode project, use the Swift Package Manager | ||
|
||
#### Swift Package Manager | ||
|
||
- File > Swift Packages > Add Package Dependency | ||
- Add `https://github.com/Matt54/ResizableVector.git` | ||
|
||
### Developments | ||
|
||
Pull requests are welcome :) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Sources/ResizableVector/Assets.xcassets/example.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "example.svg", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
Sources/ResizableVector/Assets.xcassets/example.imageset/example.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions
64
...tor/CrossPlatformAbstractions/CrossPlatformImageRenderer/CrossPlatformImageRenderer.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
adapted from work by Erica Sadun found here: | ||
https://gist.github.com/erica/ec3e2a4a8526e3fc3ba1fc95a0d53083#file-crossplatformdefines-swift | ||
*/ | ||
|
||
// MARK: Cocoa | ||
|
||
#if os(OSX) | ||
import Cocoa | ||
|
||
typealias GraphicsImageRenderer = MacGraphicsImageRenderer | ||
typealias GraphicsImageRendererFormat = MacGraphicsImageRendererFormat | ||
typealias GraphicsImageRendererContext = MacGraphicsImageRendererContext | ||
|
||
class MacGraphicsImageRendererFormat: NSObject { | ||
var opaque: Bool = false | ||
var prefersExtendedRange: Bool = false | ||
var scale: CGFloat = 2.0 | ||
var bounds: CGRect = .zero | ||
} | ||
|
||
class MacGraphicsImageRendererContext: NSObject { | ||
var format: GraphicsImageRendererFormat | ||
override init() { | ||
self.format = GraphicsImageRendererFormat() | ||
super.init() | ||
} | ||
} | ||
|
||
class MacGraphicsImageRenderer: NSObject { | ||
let format: GraphicsImageRendererFormat | ||
let bounds: CGRect | ||
|
||
init(bounds: CGRect, format: GraphicsImageRendererFormat) { | ||
(self.bounds, self.format) = (bounds, format) | ||
self.format.bounds = self.bounds | ||
super.init() | ||
} | ||
|
||
convenience init(size: CGSize) { | ||
self.init(bounds: CGRect(origin: .zero, size: size), format: GraphicsImageRendererFormat()) | ||
} | ||
|
||
func image(actions: @escaping (GraphicsImageRendererContext) -> Void) -> NSImage { | ||
let image = NSImage(size: format.bounds.size, flipped: false) { | ||
(_: NSRect) -> Bool in | ||
|
||
let imageContext = GraphicsImageRendererContext() | ||
imageContext.format = self.format | ||
actions(imageContext) | ||
|
||
return true | ||
} | ||
return image | ||
} | ||
} | ||
|
||
// MARK: UIKit | ||
|
||
#else | ||
import UIKit | ||
|
||
typealias GraphicsImageRenderer = UIGraphicsImageRenderer | ||
#endif |
27 changes: 27 additions & 0 deletions
27
Sources/ResizableVector/CrossPlatformAbstractions/MakeImageAbstractor.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// MakeImageAbstractor.swift | ||
// Created by Matt Pfeiffer on 2/27/22. | ||
|
||
import SwiftUI | ||
|
||
class MakeImageAbstractor { | ||
static func makeResizedImage(name: String, bundle: Bundle? = nil, frame: CGSize, keepAspectRatio: Bool) -> Image? { | ||
guard let platformImage = PlatformImage.makePlatformImage(named: name, in: bundle) else { return nil } | ||
let resizeTo = keepAspectRatio ? MakeImageAbstractor.getSizeWithAspectRatio(image: platformImage, newSize: frame) : frame | ||
return Image(platformImage: platformImage.resized(to: resizeTo)) | ||
} | ||
|
||
fileprivate static func getSizeWithAspectRatio(image: PlatformImage, newSize: CGSize) -> CGSize { | ||
var scaledSize = newSize | ||
var scaleFactor: CGFloat | ||
if image.size.width > image.size.height { | ||
scaleFactor = image.size.width / image.size.height | ||
scaledSize.width = newSize.height | ||
scaledSize.height = newSize.height / scaleFactor | ||
} else { | ||
scaleFactor = image.size.height / image.size.width | ||
scaledSize.height = newSize.width | ||
scaledSize.width = newSize.width / scaleFactor | ||
} | ||
return scaledSize | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
Sources/ResizableVector/CrossPlatformAbstractions/PlatformImage.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// PlatformImage.swift | ||
// Created by Matt Pfeiffer on 2/27/22. | ||
|
||
import SwiftUI | ||
|
||
extension PlatformImage { | ||
func resized(to size: CGSize) -> PlatformImage { | ||
return GraphicsImageRenderer(size: size).image { _ in | ||
self.draw(in: CGRect(origin: .zero, size: size)) | ||
} | ||
} | ||
} | ||
|
||
// MARK: Cocoa | ||
|
||
#if os(OSX) | ||
import Cocoa | ||
|
||
typealias PlatformImage = NSImage | ||
|
||
extension PlatformImage { | ||
static func makePlatformImage(named: String, in bundle: Bundle?) -> PlatformImage? { | ||
if let bundle = bundle { | ||
return bundle.image(forResource: named) | ||
} else { | ||
return PlatformImage(named: named) | ||
} | ||
} | ||
} | ||
|
||
extension Image { | ||
init(platformImage: PlatformImage) { | ||
self.init(nsImage: platformImage) | ||
} | ||
} | ||
|
||
// MARK: UIKit | ||
|
||
#else | ||
import UIKit | ||
|
||
typealias PlatformImage = UIImage | ||
|
||
extension PlatformImage { | ||
static func makePlatformImage(named: String, in bundle: Bundle?) -> PlatformImage? { | ||
return PlatformImage(named: named, in: bundle, with: nil) | ||
} | ||
} | ||
|
||
extension Image { | ||
init(platformImage: PlatformImage) { | ||
self.init(uiImage: platformImage) | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,84 @@ | ||
public struct ResizableVector { | ||
public private(set) var text = "Hello, World!" | ||
// ResizableVector.swift | ||
// Created by Matt Pfeiffer on 2/27/22. | ||
|
||
public init() { | ||
import SwiftUI | ||
|
||
public struct ResizableVector: View { | ||
var name: String | ||
var bundle: Bundle? | ||
var keepAspectRatio: Bool = false | ||
|
||
private var aspectRatio: CGFloat? | ||
|
||
public init(_ name: String) { | ||
self.name = name | ||
} | ||
|
||
public init(_ name: String, bundle: Bundle?) { | ||
self.name = name | ||
self.bundle = bundle | ||
} | ||
|
||
public init(_ name: String, keepAspectRatio: Bool) { | ||
self.name = name | ||
self.keepAspectRatio = keepAspectRatio | ||
aspectRatio = keepAspectRatio ? getAspectRatio(name, bundle: bundle) : nil | ||
} | ||
|
||
public init(_ name: String, bundle: Bundle?, keepAspectRatio: Bool) { | ||
self.name = name | ||
self.bundle = bundle | ||
self.keepAspectRatio = keepAspectRatio | ||
aspectRatio = keepAspectRatio ? getAspectRatio(name, bundle: bundle) : nil | ||
} | ||
|
||
private func getAspectRatio(_ name: String, bundle: Bundle?) -> CGFloat? { | ||
guard let image = PlatformImage.makePlatformImage(named: name, in: nil) else { return nil } | ||
let width = image.size.width | ||
let height = image.size.height | ||
return width/height | ||
} | ||
|
||
public var body: some View { | ||
Group { | ||
if keepAspectRatio { | ||
Color.clear | ||
.aspectRatio(aspectRatio, contentMode: .fit) | ||
} else { | ||
Color.clear | ||
} | ||
} | ||
.overlay ( | ||
GeometryReader { | ||
geometry in | ||
MakeImageAbstractor.makeResizedImage(name: name, | ||
bundle: bundle, | ||
frame: geometry.size, | ||
keepAspectRatio: keepAspectRatio) | ||
} | ||
) | ||
} | ||
} | ||
|
||
struct ResizableVector_Previews: PreviewProvider { | ||
static var previews: some View { | ||
HStack { | ||
VStack{ | ||
Text("ResizeableVector()") | ||
ResizableVector("example", bundle: Bundle.module, keepAspectRatio: true) | ||
.frame(width: 200) | ||
.background(Color.green) | ||
} | ||
|
||
VStack{ | ||
Text("Image()") | ||
Image("example", bundle: Bundle.module) | ||
.resizable() | ||
.aspectRatio(contentMode: .fit) | ||
.frame(width: 200) | ||
.background(Color.green) | ||
} | ||
} | ||
.previewLayout(.fixed(width: 850, height: 400)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters