Skip to content

Commit b873052

Browse files
committed
Update SVGPath to 1.1.1
1 parent dc9c304 commit b873052

File tree

8 files changed

+357
-56
lines changed

8 files changed

+357
-56
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ let package = Package(
2222
),
2323
.package(
2424
url: "https://github.com/nicklockwood/SVGPath.git",
25-
.upToNextMinor(from: "1.0.2")
25+
.upToNextMinor(from: "1.1.1")
2626
),
2727
],
2828
targets: [

SVGPath/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## [1.1.1](https://github.com/nicklockwood/LRUCache/releases/tag/1.1.1) (2022-07-27)
2+
3+
- Fixed bug where coordinates were flipped vertically when serializing path to string
4+
5+
## [1.1.0](https://github.com/nicklockwood/LRUCache/releases/tag/1.1.0) (2022-07-24)
6+
7+
- Added `SVGPath(cgPath:)` initializer for converting `CGPath` to `SVGPath`
8+
- Added `SVGPath.string(with:)` method for serializing an `SVGPath` object back to string form
9+
- Added `SVGPath.points()` and `SVGPath.getPoints()` methods for extracting path data
10+
- Fixed compiler warning on older Xcode versions
11+
- Fixed warnings on latest Xcode
12+
113
## [1.0.2](https://github.com/nicklockwood/LRUCache/releases/tag/1.0.2) (2022-04-15)
214

315
- Added `SVGArc.asBezierPath()` method for converting arc to Bezier curves without needing Core Graphics

SVGPath/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- [Introduction](#introduction)
99
- [Installation](#installation)
1010
- [Usage](#usage)
11+
- [Advanced Usage](#advanced-usage)
1112
- [Credits](#credits)
1213

1314

@@ -56,6 +57,51 @@ let cgPath = try CGPath.from(svgPath: "M150 0 L75 200 L225 200 Z")
5657
Once you have a `CGPath` you can render it on iOS or macOS using a CoreGraphics context or a `CAShapeLayer`.
5758

5859

60+
# Advanced Usage
61+
62+
You can convert a `CGPath` to an `SVGPath` using the `init(cgPath:)` initializer:
63+
64+
```swift
65+
let rect = CGRect(x: 0, y: 0, width: 10, height: 10)
66+
let cgPath = CGPath(rect: rect, transform: nil)
67+
let svgPath = SVGPath(cgPath: cgPath)
68+
```
69+
70+
To convert an `SVGPath` back into a `String`, use the `string(with:)` method. This can be useful for exporting a `CGPath` as an SVG string:
71+
72+
```swift
73+
let svgPath = SVGPath(cgPath: ...)
74+
let options = SVGPath.WriteOptions(prettyPrinted: true, wrapWidth: 80)
75+
let string = svgPath.string(with: options)
76+
```
77+
78+
It's also possible to use `SVGPath` without CoreGraphics. You can iterate over the raw path components using the `commands` property:
79+
80+
```swift
81+
for command in svgPath.commands {
82+
switch command {
83+
case .moveTo(let point):
84+
...
85+
case .lineTo(let point):
86+
...
87+
default:
88+
...
89+
}
90+
}
91+
```
92+
93+
Alternatively, you can use the `points()` or `getPoints()` methods to convert the entire path to a flar array of points at your preferred level of detail.
94+
95+
These can be used to render the path using simple straight line segments using any graphics API you choose:
96+
97+
```swift
98+
let detail = 10 // number of sample points used to represent curved segments
99+
let points = svgPath.points(withDetail: detail)
100+
```
101+
102+
**NOTE:** coordinates are stored with inverted Y coordinates internally, to match the coordinate system used by Core Graphics on macOS/iOS.
103+
104+
59105
# Credits
60106

61107
The SVGPath library is primarily the work of [Nick Lockwood](https://github.com/nicklockwood).

SVGPath/SVGPath.xcodeproj/project.pbxproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
/* Begin PBXShellScriptBuildPhase section */
213213
01F2A9E9250177730081CDF5 /* Format Code */ = {
214214
isa = PBXShellScriptBuildPhase;
215+
alwaysOutOfDate = 1;
215216
buildActionMask = 2147483647;
216217
files = (
217218
);
@@ -429,7 +430,7 @@
429430
"@executable_path/../Frameworks",
430431
"@loader_path/Frameworks",
431432
);
432-
MARKETING_VERSION = 1.0.2;
433+
MARKETING_VERSION = 1.1.1;
433434
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=75";
434435
PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.SVGPath;
435436
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
@@ -463,7 +464,7 @@
463464
"@executable_path/../Frameworks",
464465
"@loader_path/Frameworks",
465466
);
466-
MARKETING_VERSION = 1.0.2;
467+
MARKETING_VERSION = 1.1.1;
467468
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=75";
468469
PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.SVGPath;
469470
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";

SVGPath/Sources/SVGPath+CoreGraphics.swift

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import CoreGraphics
3535
import Foundation
3636

37+
// MARK: SVGPath to CGPath
38+
3739
public extension CGPath {
3840
static func from(svgPath: String) throws -> CGPath {
3941
from(svgPath: try SVGPath(string: svgPath))
@@ -53,12 +55,6 @@ public extension CGPoint {
5355
}
5456
}
5557

56-
public extension SVGPoint {
57-
init(_ cgPoint: CGPoint) {
58-
self.init(x: Double(cgPoint.x), y: Double(cgPoint.y))
59-
}
60-
}
61-
6258
private extension CGMutablePath {
6359
func addCommand(_ command: SVGCommand) {
6460
switch command {
@@ -85,4 +81,64 @@ private extension CGMutablePath {
8581
}
8682
}
8783

84+
// MARK: CGPath to SVGPath
85+
86+
public extension SVGPath {
87+
init(cgPath: CGPath) {
88+
var commands = [SVGCommand]()
89+
cgPath.enumerate {
90+
let command: SVGCommand
91+
switch $0.type {
92+
case .moveToPoint:
93+
command = .moveTo(SVGPoint($0.points[0]))
94+
case .closeSubpath:
95+
command = .end
96+
case .addLineToPoint:
97+
command = .lineTo(SVGPoint($0.points[0]))
98+
case .addQuadCurveToPoint:
99+
let p1 = $0.points[0], p2 = $0.points[1]
100+
command = .quadratic(SVGPoint(p1), SVGPoint(p2))
101+
case .addCurveToPoint:
102+
let p1 = $0.points[0], p2 = $0.points[1], p3 = $0.points[2]
103+
command = .cubic(SVGPoint(p1), SVGPoint(p2), SVGPoint(p3))
104+
@unknown default:
105+
return
106+
}
107+
commands.append(command)
108+
}
109+
self.init(commands: commands)
110+
}
111+
}
112+
113+
public extension SVGPoint {
114+
init(_ cgPoint: CGPoint) {
115+
self.init(x: Double(cgPoint.x), y: Double(cgPoint.y))
116+
}
117+
}
118+
119+
extension CGPath {
120+
func enumerate(_ fn: @convention(block) (CGPathElement) -> Void) {
121+
if #available(iOS 11.0, tvOS 11.0, OSX 10.13, *) {
122+
applyWithBlock { fn($0.pointee) }
123+
return
124+
}
125+
126+
// Fallback for earlier OSes
127+
typealias Block = @convention(block) (CGPathElement) -> Void
128+
let callback: @convention(c) (
129+
UnsafeMutableRawPointer,
130+
UnsafePointer<CGPathElement>
131+
) -> Void = { info, element in
132+
unsafeBitCast(info, to: Block.self)(element.pointee)
133+
}
134+
withoutActuallyEscaping(fn) { block in
135+
let block = unsafeBitCast(block, to: UnsafeMutableRawPointer.self)
136+
self.apply(info: block, function: unsafeBitCast(
137+
callback,
138+
to: CGPathApplierFunction.self
139+
))
140+
}
141+
}
142+
}
143+
88144
#endif

0 commit comments

Comments
 (0)