diff --git a/Source/model/draw/Stroke.swift b/Source/model/draw/Stroke.swift index 162cf49e..e09c5f77 100644 --- a/Source/model/draw/Stroke.swift +++ b/Source/model/draw/Stroke.swift @@ -7,12 +7,14 @@ open class Stroke { open let cap: LineCap open let join: LineJoin open let dashes: [Double] + open let offset: Double - public init(fill: Fill = Color.black, width: Double = 1, cap: LineCap = .butt, join: LineJoin = .miter, dashes: [Double] = []) { + public init(fill: Fill = Color.black, width: Double = 1, cap: LineCap = .butt, join: LineJoin = .miter, dashes: [Double] = [], offset: Double = 0.0) { self.fill = fill self.width = width self.cap = cap self.join = join self.dashes = dashes + self.offset = offset } } diff --git a/Source/render/ShapeRenderer.swift b/Source/render/ShapeRenderer.swift index 05ac7e16..f519df4f 100644 --- a/Source/render/ShapeRenderer.swift +++ b/Source/render/ShapeRenderer.swift @@ -167,14 +167,9 @@ class ShapeRenderer: NodeRenderer { ctx!.setLineWidth(CGFloat(stroke.width)) ctx!.setLineJoin(RenderUtils.mapLineJoin(stroke.join)) ctx!.setLineCap(RenderUtils.mapLineCap(stroke.cap)) - let dashes = stroke.dashes - if !dashes.isEmpty { - var floatDashes = [CGFloat]() - dashes.forEach { dash in - floatDashes.append(CGFloat(dash)) - } - - ctx?.setLineDash(phase: 0.0, lengths: floatDashes) + if !stroke.dashes.isEmpty { + ctx?.setLineDash(phase: CGFloat(stroke.offset), + lengths: stroke.dashes.map{ CGFloat($0) }) } } diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 1ea30fe5..0da716e3 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -41,7 +41,7 @@ open class SVGParser { return SVGParser(text).parse() } - let availableStyleAttributes = ["stroke", "stroke-width", "stroke-opacity", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", + let availableStyleAttributes = ["stroke", "stroke-width", "stroke-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "fill", "text-anchor", "clip-path", "fill-opacity", "stop-color", "stop-opacity", "font-family", "font-size", @@ -620,7 +620,8 @@ open class SVGParser { width: getStrokeWidth(styleParts), cap: getStrokeCap(styleParts), join: getStrokeJoin(styleParts), - dashes: getStrokeDashes(styleParts)) + dashes: getStrokeDashes(styleParts), + offset: getStrokeOffset(styleParts)) } return .none @@ -683,6 +684,13 @@ open class SVGParser { } return dashes } + + fileprivate func getStrokeOffset(_ styleParts: [String: String]) -> Double { + if let strokeOffset = styleParts["stroke-dashoffset"], let offset = Double(strokeOffset) { // TODO use doubleFromString once it's merged + return offset + } + return 0 + } fileprivate func getTag(_ element: SWXMLHash.XMLElement) -> [String] { let id = element.allAttributes["id"]?.text diff --git a/Source/svg/SVGSerializer.swift b/Source/svg/SVGSerializer.swift index 6856a59d..5b5555a0 100644 --- a/Source/svg/SVGSerializer.swift +++ b/Source/svg/SVGSerializer.swift @@ -247,6 +247,15 @@ open class SVGSerializer { result += " stroke-linejoin=\"\(strokeJoin)\"" } } + if let strokeDashes = stroke?.dashes, strokeDashes.count > 0 { + let dashes = strokeDashes.map{ String($0) }.joined(separator: ",") + result += " stroke-dasharray=\"\(dashes)\"" + } + if let strokeOffset = stroke?.offset { + if strokeOffset != 0 { + result += " stroke-dashoffset=\"\(strokeOffset)\"" + } + } return result }