Skip to content

Commit 3abe879

Browse files
committed
Update SVGPath to 1.1.3
1 parent 32b72ad commit 3abe879

File tree

8 files changed

+124
-48
lines changed

8 files changed

+124
-48
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.1.1")
25+
.upToNextMinor(from: "1.1.3")
2626
),
2727
],
2828
targets: [

SVGPath/CHANGELOG.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## [1.1.3](https://github.com/nicklockwood/LRUCache/releases/tag/1.1.3) (2023-03-17)
2+
3+
- Fixed bug with parsing paths that use a leading `+` as a delimiter between numbers
4+
5+
## [1.1.2](https://github.com/nicklockwood/LRUCache/releases/tag/1.1.2) (2023-03-08)
6+
7+
- Fixed bug where relative coordinates were calculated incorrectly after an `end` command
8+
19
## [1.1.1](https://github.com/nicklockwood/LRUCache/releases/tag/1.1.1) (2022-07-27)
210

311
- Fixed bug where coordinates were flipped vertically when serializing path to string
@@ -12,12 +20,12 @@
1220

1321
## [1.0.2](https://github.com/nicklockwood/LRUCache/releases/tag/1.0.2) (2022-04-15)
1422

15-
- Added `SVGArc.asBezierPath()` method for converting arc to Bezier curves without needing Core Graphics
23+
- Added `SVGArc.asBezierPath()` method for converting arcs to Bezier curves without Core Graphics
1624

1725
## [1.0.1](https://github.com/nicklockwood/LRUCache/releases/tag/1.0.1) (2022-04-04)
1826

19-
- Fix parsing scientific numbers
20-
- Support implicit 'lineto' commands
27+
- Fixed parsing scientific numbers
28+
- Added support for implicit `lineTo` commands
2129

2230
## [1.0.0](https://github.com/nicklockwood/LRUCache/releases/tag/1.0.0) (2022-01-08)
2331

SVGPath/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Platforms](https://img.shields.io/badge/platforms-iOS%20|%20Mac%20|%20tvOS%20|%20Linux-lightgray.svg)]()
44
[![Swift 5.1](https://img.shields.io/badge/swift-5.1-red.svg?style=flat)](https://developer.apple.com/swift)
55
[![License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://opensource.org/licenses/MIT)
6-
[![Twitter](https://img.shields.io/badge/twitter-@nicklockwood-blue.svg)](http://twitter.com/nicklockwood)
6+
[![Mastodon](https://img.shields.io/badge/mastodon-@nicklockwood@mastodon.social-636dff.svg)](https://mastodon.social/@nicklockwood)
77

88
- [Introduction](#introduction)
99
- [Installation](#installation)

SVGPath/SVGPath.xcodeproj/project.pbxproj

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
isa = PBXProject;
161161
attributes = {
162162
LastSwiftUpdateCheck = 1010;
163-
LastUpgradeCheck = 1410;
163+
LastUpgradeCheck = 1400;
164164
ORGANIZATIONNAME = "Nick Lockwood";
165165
TargetAttributes = {
166166
016FAB2821BFE78100AF60DC = {
@@ -425,14 +425,12 @@
425425
FRAMEWORK_VERSION = A;
426426
INFOPLIST_FILE = Sources/Info.plist;
427427
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
428-
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
429428
LD_RUNPATH_SEARCH_PATHS = (
430429
"$(inherited)",
431430
"@executable_path/../Frameworks",
432431
"@loader_path/Frameworks",
433432
);
434-
MACOSX_DEPLOYMENT_TARGET = 10.13;
435-
MARKETING_VERSION = 1.1.1;
433+
MARKETING_VERSION = 1.1.3;
436434
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=75";
437435
PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.SVGPath;
438436
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";
@@ -461,14 +459,12 @@
461459
FRAMEWORK_VERSION = A;
462460
INFOPLIST_FILE = Sources/Info.plist;
463461
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
464-
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
465462
LD_RUNPATH_SEARCH_PATHS = (
466463
"$(inherited)",
467464
"@executable_path/../Frameworks",
468465
"@loader_path/Frameworks",
469466
);
470-
MACOSX_DEPLOYMENT_TARGET = 10.13;
471-
MARKETING_VERSION = 1.1.1;
467+
MARKETING_VERSION = 1.1.3;
472468
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=75";
473469
PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.SVGPath;
474470
PRODUCT_MODULE_NAME = "$(PRODUCT_NAME:c99extidentifier)";

SVGPath/SVGPath.xcodeproj/xcshareddata/xcschemes/SVGPath.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1420"
3+
LastUpgradeVersion = "1400"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

SVGPath/Sources/SVGPath+CoreGraphics.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@
1111
// https://github.com/nicklockwood/SVGPath
1212
//
1313
// Permission is hereby granted, free of charge, to any person obtaining a copy
14-
// of this software and associated documentation files (the "Software"), to deal
15-
// in the Software without restriction, including without limitation the rights
16-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17-
// copies of the Software, and to permit persons to whom the Software is
14+
// of this software and associated documentation files (the "Software"), to
15+
// deal in the Software without restriction, including without limitation the
16+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
17+
// sell copies of the Software, and to permit persons to whom the Software is
1818
// furnished to do so, subject to the following conditions:
1919
//
20-
// The above copyright notice and this permission notice shall be included in all
21-
// copies or substantial portions of the Software.
20+
// The above copyright notice and this permission notice shall be included in
21+
// all copies or substantial portions of the Software.
2222
//
2323
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2424
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2525
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2626
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29-
// SOFTWARE.
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29+
// IN THE SOFTWARE.
3030
//
3131

3232
#if canImport(CoreGraphics)
@@ -38,7 +38,7 @@ import Foundation
3838

3939
public extension CGPath {
4040
static func from(svgPath: String) throws -> CGPath {
41-
from(svgPath: try SVGPath(string: svgPath))
41+
try from(svgPath: SVGPath(string: svgPath))
4242
}
4343

4444
static func from(svgPath: SVGPath) -> CGPath {

SVGPath/Sources/SVGPath.swift

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@
1111
// https://github.com/nicklockwood/SVGPath
1212
//
1313
// Permission is hereby granted, free of charge, to any person obtaining a copy
14-
// of this software and associated documentation files (the "Software"), to deal
15-
// in the Software without restriction, including without limitation the rights
16-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17-
// copies of the Software, and to permit persons to whom the Software is
14+
// of this software and associated documentation files (the "Software"), to
15+
// deal in the Software without restriction, including without limitation the
16+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
17+
// sell copies of the Software, and to permit persons to whom the Software is
1818
// furnished to do so, subject to the following conditions:
1919
//
20-
// The above copyright notice and this permission notice shall be included in all
21-
// copies or substantial portions of the Software.
20+
// The above copyright notice and this permission notice shall be included in
21+
// all copies or substantial portions of the Software.
2222
//
2323
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2424
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2525
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2626
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29-
// SOFTWARE.
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29+
// IN THE SOFTWARE.
3030
//
3131

3232
import Foundation
@@ -70,7 +70,7 @@ public struct SVGPath: Hashable {
7070
func lineToVertical() throws -> SVGCommand {
7171
let numbers = try assertArgs(1)
7272
return .lineTo(SVGPoint(
73-
x: isRelative ? 0 : (commands.last?.point.x ?? 0),
73+
x: isRelative ? 0 : commands.lastPoint.x,
7474
y: -numbers[0]
7575
))
7676
}
@@ -79,7 +79,7 @@ public struct SVGPath: Hashable {
7979
let numbers = try assertArgs(1)
8080
return .lineTo(SVGPoint(
8181
x: numbers[0],
82-
y: isRelative ? 0 : (commands.last?.point.y ?? 0)
82+
y: isRelative ? 0 : commands.lastPoint.y
8383
))
8484
}
8585

@@ -161,8 +161,9 @@ public struct SVGPath: Hashable {
161161
}
162162

163163
func appendCommand(_ command: SVGCommand) {
164-
let last = isRelative ? commands.last : nil
165-
commands.append(command.relative(to: last))
164+
commands.append(
165+
isRelative ? command.relative(to: commands.lastPoint) : command
166+
)
166167
}
167168

168169
func processCommand() throws {
@@ -195,20 +196,18 @@ public struct SVGPath: Hashable {
195196

196197
for char in string.unicodeScalars {
197198
switch char {
198-
case "0" ... "9", "E", "e", "+":
199+
case "0" ... "9", "E", "e":
199200
number.append(Character(char))
200201
case ".":
201202
if number.contains(".") {
202203
try processNumber()
203204
}
204205
number.append(".")
205-
case "-":
206-
if let last = number.last, "eE".contains(last) {
207-
number.append(Character(char))
208-
} else {
206+
case "-", "+":
207+
if let last = number.last, !"eE".contains(last) {
209208
try processNumber()
210-
number = "-"
211209
}
210+
number.append(Character(char))
212211
case "a" ... "z", "A" ... "Z":
213212
try processNumber()
214213
try processCommand()
@@ -309,6 +308,17 @@ private extension Character {
309308
}
310309
}
311310

311+
private extension Array where Element == SVGCommand {
312+
var lastPoint: SVGPoint {
313+
for command in reversed() {
314+
if let point = command.point {
315+
return point
316+
}
317+
}
318+
return .zero
319+
}
320+
}
321+
312322
public enum SVGError: Error, Hashable {
313323
case unexpectedToken(String)
314324
case unexpectedArgument(for: String, expected: Int)
@@ -336,7 +346,7 @@ public enum SVGCommand: Hashable {
336346
}
337347

338348
public extension SVGCommand {
339-
var point: SVGPoint {
349+
var point: SVGPoint? {
340350
switch self {
341351
case let .moveTo(point),
342352
let .lineTo(point),
@@ -346,7 +356,7 @@ public extension SVGCommand {
346356
case let .arc(arc):
347357
return arc.end
348358
case .end:
349-
return .zero
359+
return nil
350360
}
351361
}
352362

@@ -431,10 +441,7 @@ public extension SVGCommand {
431441
}
432442
}
433443

434-
fileprivate func relative(to last: SVGCommand?) -> SVGCommand {
435-
guard let last = last?.point else {
436-
return self
437-
}
444+
fileprivate func relative(to last: SVGPoint) -> SVGCommand {
438445
switch self {
439446
case let .moveTo(point):
440447
return .moveTo(point + last)

SVGPath/Tests/SVGPathTests.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ class SVGPathTests: XCTestCase {
8888
XCTAssertEqual(svgPath, expected)
8989
}
9090

91+
func testNumbersWithPlusAsSeparator() throws {
92+
let svgPath = try SVGPath(string: "M0 0L.57+5Z")
93+
let expected = SVGPath(commands: [
94+
.moveTo(.zero),
95+
.lineTo(.init(x: 0.57, y: -5)),
96+
.end,
97+
])
98+
XCTAssertEqual(svgPath, expected)
99+
}
100+
91101
func testAbsoluteHorizontalRule() throws {
92102
let svgPath = try SVGPath(string: "M0 0L10 10H0Z")
93103
let expected = SVGPath(commands: [
@@ -142,4 +152,59 @@ class SVGPathTests: XCTestCase {
142152
])
143153
XCTAssertEqual(svgPath, expected)
144154
}
155+
156+
func testRelativePathAfterEndCommand() throws {
157+
let svgPath = try SVGPath(string: """
158+
m246.7881938,177.5848955c-13.9366996-.4842-27.8722993-.77-41.8169989
159+
-.8486,6.3990998,6.5819998,12.7983997,13.1638997,19.1974995,19.7456995,
160+
7.3688998-6.5151998,14.8972996-12.8044997,22.6194994-18.8970995Zm
161+
-45.4452989,2.3984999c-7.2300998,6.6123998-14.2535996,13.4058997
162+
-21.1025995,20.4121995,12.8467997,13.5595997,25.6935994,27.1189993,
163+
38.540699,40.678399,6.9114998-7.2348998,14.0072996-14.2496996,
164+
21.3211995-21.0778995-12.9196997-13.3375997-25.8395993-26.6751993
165+
-38.759299-40.012699Z
166+
""")
167+
let expected = SVGPath(commands: [
168+
.moveTo(.init(x: 246.7881938, y: -177.5848955)),
169+
.cubic(
170+
.init(x: 232.8514942, y: -177.1006955),
171+
.init(x: 218.91589449999998, y: -176.81489549999998),
172+
.init(x: 204.9711949, y: -176.73629549999998)
173+
),
174+
.cubic(
175+
.init(x: 211.3702947, y: -183.3182953),
176+
.init(x: 217.7695946, y: -189.90019519999998),
177+
.init(x: 224.1686944, y: -196.48199499999998)
178+
),
179+
.cubic(
180+
.init(x: 231.5375942, y: -189.96679519999998),
181+
.init(x: 239.065994, y: -183.67749529999998),
182+
.init(x: 246.7881938, y: -177.5848955)
183+
),
184+
.end,
185+
.moveTo(.init(x: 201.34289489999998, y: -179.98339539999998)),
186+
.cubic(
187+
.init(x: 194.11279509999997, y: -186.59579519999997),
188+
.init(x: 187.08929529999997, y: -193.38929509999997),
189+
.init(x: 180.24029539999998, y: -200.3955949)
190+
),
191+
.cubic(
192+
.init(x: 193.08709509999997, y: -213.9551946),
193+
.init(x: 205.9338948, y: -227.51459419999998),
194+
.init(x: 218.78099439999997, y: -241.0739939)
195+
),
196+
.cubic(
197+
.init(x: 225.69249419999997, y: -233.8390941),
198+
.init(x: 232.78829399999998, y: -226.82429430000002),
199+
.init(x: 240.10219389999997, y: -219.9960944)
200+
),
201+
.cubic(
202+
.init(x: 227.18249419999998, y: -206.6584947),
203+
.init(x: 214.26259459999997, y: -193.3208951),
204+
.init(x: 201.34289489999998, y: -179.9833954)
205+
),
206+
.end,
207+
])
208+
XCTAssertEqual(svgPath, expected)
209+
}
145210
}

0 commit comments

Comments
 (0)