         self.type = type
     }
     
-    private mutating func relativeTo (other:SVGCommand?, coords: Coordinates) -> SVGCommand {
-        if coords == .Absolute { return self }
+    private func relativeTo (other:SVGCommand?) -> SVGCommand {
         if let otherPoint = other?.point {
-            point = point + otherPoint
-            control1 = control1 + otherPoint
-            control2 = control2 + otherPoint
+            return SVGCommand(control1 + otherPoint, control2 + otherPoint, point + otherPoint, type: type)
         }
         return self
     }
 }
 
-private typealias SVGCommandBuilder = ([CGFloat], SVGCommand?, Coordinates) -> [SVGCommand]
+// MARK: CGPoint helpers
 
 private func +(a:CGPoint, b:CGPoint) -> CGPoint {
     return CGPoint(x: a.x + b.x, y: a.y + b.y)


// MARK: Mm - Move

private func moveTo (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 2, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(nums[0], nums[1], type: .Move)
    }
}

// MARK: Ll - Line

private func lineTo (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 2, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(nums[0], nums[1], type: .Line)
    }
}

// MARK: Vv - Vertical Line

private func lineToVertical (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 1, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(coords == .Absolute ? last?.point.x ?? 0 : 0, nums[0], type: .Line)
    }
}

// MARK: Hh - Horizontal Line

private func lineToHorizontal (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 1, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(nums[0], coords == .Absolute ? last?.point.y ?? 0 : 0, type: .Line)
    }
}

// MARK: Qq - Quadratic Curve To

private func quadBroken (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 4, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(nums[0], nums[1], nums[2], nums[3])
    }
}

// MARK: Tt - Smooth Quadratic Curve To

private func quadSmooth (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 2, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        let lastControl = last?.control1 ?? CGPoint()
        let lastPoint = last?.point ?? CGPoint()
        var control = lastPoint - lastControl
        if coords == .Absolute {
            control = control + lastPoint
        }
        return SVGCommand(control.x, control.y, nums[0], nums[1])
    }
}

// MARK: Cc - Cubic Curve To

private func cubeBroken (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 6, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        return SVGCommand(nums[0], nums[1], nums[2], nums[3], nums[4], nums[5])
    }
}

// MARK: Ss - Smooth Cubic Curve To

private func cubeSmooth (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
    return take(numbers, 4, lastCommand) {
        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
        var lastControl = last?.control2 ?? CGPoint()
        let lastPoint = last?.point ?? CGPoint()
        if (last?.type ?? .Line) != .CubeCurve {
            lastControl = lastPoint
        }
        var control = lastPoint - lastControl
        if coords == .Absolute {
            control = control + lastPoint
        }
        return SVGCommand(control.x, control.y, nums[0], nums[1], nums[2], nums[3])
    }
}


public class SVGPath {
    public var commands: [SVGCommand] = []
    private var builder: SVGCommandBuilder = moveTo
    private var coords: Coordinates = .Absolute
    private var stride: Int = 2
    private var numbers = ""

    public init (_ string: String) {
        for char in string {
            switch char {
            case "M": use(.Absolute, 2, moveTo)
            case "m": use(.Relative, 2, moveTo)
            case "L": use(.Absolute, 2, lineTo)
            case "l": use(.Relative, 2, lineTo)
            case "V": use(.Absolute, 1, lineToVertical)
            case "v": use(.Relative, 1, lineToVertical)
            case "H": use(.Absolute, 1, lineToHorizontal)
            case "h": use(.Relative, 1, lineToHorizontal)
            case "Q": use(.Absolute, 4, quadBroken)
            case "q": use(.Relative, 4, quadBroken)
            case "T": use(.Absolute, 2, quadSmooth)
            case "t": use(.Relative, 2, quadSmooth)
            case "C": use(.Absolute, 6, cubeBroken)
            case "c": use(.Relative, 6, cubeBroken)
            case "S": use(.Absolute, 4, cubeSmooth)
            case "s": use(.Relative, 4, cubeSmooth)
            default: numbers.append(char)
            }
        }
        finishLastCommand()
    }
    
    private func use (coords: Coordinates, _ stride: Int, _ builder: SVGCommandBuilder) {
        finishLastCommand()
        self.builder = builder
        self.coords = coords
        self.stride = stride
    }
    
    private func finishLastCommand () {
        for command in take(SVGPath.parseNumbers(numbers), stride, coords, commands.last, builder) {
            commands.append(coords == .Relative ? command.relativeTo(commands.last) : command)
        }
        numbers = ""
    }
