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
3232import 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+
312322public 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
338348public 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)
0 commit comments