From bc50a8a20e07e4b0984f401dc5876590722ff3a6 Mon Sep 17 00:00:00 2001 From: Paco Wong Date: Thu, 27 Jun 2024 21:42:22 +0800 Subject: [PATCH 1/5] Add parser for tspan --- Source/Parser/SVG/Elements/SVGTextParser.swift | 10 +++++++++- Source/Parser/SVG/SVGParser.swift | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Source/Parser/SVG/Elements/SVGTextParser.swift b/Source/Parser/SVG/Elements/SVGTextParser.swift index 7f92119..6538ad7 100644 --- a/Source/Parser/SVG/Elements/SVGTextParser.swift +++ b/Source/Parser/SVG/Elements/SVGTextParser.swift @@ -21,9 +21,17 @@ class SVGTextParser: SVGBaseElementParser { if let textNode = context.element.contents.first as? XMLText { let trimmed = textNode.text.trimmingCharacters(in: .whitespacesAndNewlines).processingWhitespaces() + return SVGText(text: trimmed, font: font, fill: SVGHelper.parseFill(context.styles, context.index), stroke: SVGHelper.parseStroke(context.styles, index: context.index), textAnchor: textAnchor, transform: transform) } - return .none + return SVGGroup(contents: parseContents(context: context, delegate: delegate)) + //return .none + } + + func parseContents(context: SVGNodeContext, delegate: (XMLElement) -> SVGNode?) -> [SVGNode] { + return context.element.contents + .compactMap { $0 as? XMLElement } + .compactMap { delegate($0) } } private func parseTextAnchor(_ string: String?) -> HorizontalAlignment { diff --git a/Source/Parser/SVG/SVGParser.swift b/Source/Parser/SVG/SVGParser.swift index 18f6513..10861b1 100644 --- a/Source/Parser/SVG/SVGParser.swift +++ b/Source/Parser/SVG/SVGParser.swift @@ -55,6 +55,7 @@ public struct SVGParser { "g": SVGGroupParser(), "use": SVGUseParser(), "text": SVGTextParser(), + "tspan": SVGTextParser(), "image": SVGImageParser(), "rect": SVGRectParser(), "circle": SVGCircleParser(), @@ -66,6 +67,9 @@ public struct SVGParser { ] private static func parse(context: SVGNodeContext) -> SVGNode? { + if context.element.name == "tspan" { + print("[PACO] HELLO") + } return parsers[context.element.name]?.parse(context: context) { parse(element: $0, parentContext: context) } From b04fa2277676430cc6bae922cdf8588e6b7759e6 Mon Sep 17 00:00:00 2001 From: Paco Wong Date: Fri, 28 Jun 2024 09:15:42 +0800 Subject: [PATCH 2/5] Read dx and dy for SVG text --- Source/Model/Nodes/SVGText.swift | 12 +++++++++++- Source/Parser/SVG/Elements/SVGTextParser.swift | 4 +++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Model/Nodes/SVGText.swift b/Source/Model/Nodes/SVGText.swift index 930ee46..89f7147 100644 --- a/Source/Model/Nodes/SVGText.swift +++ b/Source/Model/Nodes/SVGText.swift @@ -2,19 +2,29 @@ import SwiftUI import Combine public class SVGText: SVGNode, ObservableObject { + public struct Shift: Codable { + let dx: String? + let dy: String? + + public static let empty = Shift(dx: nil, dy: nil) + } @Published public var text: String @Published public var font: SVGFont? @Published public var fill: SVGPaint? @Published public var stroke: SVGStroke? @Published public var textAnchor: HorizontalAlignment = .leading + @Published public var contents: [SVGNode] = [] + @Published public var shift: Shift? = nil - public init(text: String, font: SVGFont? = nil, fill: SVGPaint? = SVGColor.black, stroke: SVGStroke? = nil, textAnchor: HorizontalAlignment = .leading, transform: CGAffineTransform = .identity, opaque: Bool = true, opacity: Double = 1, clip: SVGUserSpaceNode? = nil, mask: SVGNode? = nil) { + public init(text: String, font: SVGFont? = nil, fill: SVGPaint? = SVGColor.black, stroke: SVGStroke? = nil, textAnchor: HorizontalAlignment = .leading, transform: CGAffineTransform = .identity, contents: [SVGNode] = [], opaque: Bool = true, opacity: Double = 1, clip: SVGUserSpaceNode? = nil, mask: SVGNode? = nil, shift: SVGText.Shift = .empty) { self.text = text self.font = font self.fill = fill self.stroke = stroke self.textAnchor = textAnchor + self.contents = contents + self.shift = shift super.init(transform: transform, opaque: opaque, opacity: opacity, clip: clip, mask: mask) } diff --git a/Source/Parser/SVG/Elements/SVGTextParser.swift b/Source/Parser/SVG/Elements/SVGTextParser.swift index 6538ad7..8bc14f7 100644 --- a/Source/Parser/SVG/Elements/SVGTextParser.swift +++ b/Source/Parser/SVG/Elements/SVGTextParser.swift @@ -19,10 +19,12 @@ class SVGTextParser: SVGBaseElementParser { let y = SVGHelper.parseCGFloat(context.properties, "y") let transform = CGAffineTransform(translationX: x, y: y) + let shift = SVGText.Shift(dx: context.properties["dx"], dy: context.properties["dy"]) + if let textNode = context.element.contents.first as? XMLText { let trimmed = textNode.text.trimmingCharacters(in: .whitespacesAndNewlines).processingWhitespaces() - return SVGText(text: trimmed, font: font, fill: SVGHelper.parseFill(context.styles, context.index), stroke: SVGHelper.parseStroke(context.styles, index: context.index), textAnchor: textAnchor, transform: transform) + return SVGText(text: trimmed, font: font, fill: SVGHelper.parseFill(context.styles, context.index), stroke: SVGHelper.parseStroke(context.styles, index: context.index), textAnchor: textAnchor, transform: transform, shift: shift) } return SVGGroup(contents: parseContents(context: context, delegate: delegate)) //return .none From 87f6e9b8d80e39861840a7fca00b6245bdb86674 Mon Sep 17 00:00:00 2001 From: Paco Wong Date: Fri, 28 Jun 2024 10:42:41 +0800 Subject: [PATCH 3/5] Collect anchor string --- Source/Model/Nodes/SVGText.swift | 4 +++- Source/Parser/SVG/Elements/SVGTextParser.swift | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Model/Nodes/SVGText.swift b/Source/Model/Nodes/SVGText.swift index 89f7147..76e2832 100644 --- a/Source/Model/Nodes/SVGText.swift +++ b/Source/Model/Nodes/SVGText.swift @@ -14,10 +14,11 @@ public class SVGText: SVGNode, ObservableObject { @Published public var fill: SVGPaint? @Published public var stroke: SVGStroke? @Published public var textAnchor: HorizontalAlignment = .leading + @Published public var textAnchorString: String? = nil @Published public var contents: [SVGNode] = [] @Published public var shift: Shift? = nil - public init(text: String, font: SVGFont? = nil, fill: SVGPaint? = SVGColor.black, stroke: SVGStroke? = nil, textAnchor: HorizontalAlignment = .leading, transform: CGAffineTransform = .identity, contents: [SVGNode] = [], opaque: Bool = true, opacity: Double = 1, clip: SVGUserSpaceNode? = nil, mask: SVGNode? = nil, shift: SVGText.Shift = .empty) { + public init(text: String, font: SVGFont? = nil, fill: SVGPaint? = SVGColor.black, stroke: SVGStroke? = nil, textAnchor: HorizontalAlignment = .leading, transform: CGAffineTransform = .identity, contents: [SVGNode] = [], opaque: Bool = true, opacity: Double = 1, clip: SVGUserSpaceNode? = nil, mask: SVGNode? = nil, shift: SVGText.Shift = .empty, textAnchorString: String? = nil) { self.text = text self.font = font self.fill = fill @@ -25,6 +26,7 @@ public class SVGText: SVGNode, ObservableObject { self.textAnchor = textAnchor self.contents = contents self.shift = shift + self.textAnchorString = textAnchorString super.init(transform: transform, opaque: opaque, opacity: opacity, clip: clip, mask: mask) } diff --git a/Source/Parser/SVG/Elements/SVGTextParser.swift b/Source/Parser/SVG/Elements/SVGTextParser.swift index 8bc14f7..5e38725 100644 --- a/Source/Parser/SVG/Elements/SVGTextParser.swift +++ b/Source/Parser/SVG/Elements/SVGTextParser.swift @@ -24,7 +24,7 @@ class SVGTextParser: SVGBaseElementParser { if let textNode = context.element.contents.first as? XMLText { let trimmed = textNode.text.trimmingCharacters(in: .whitespacesAndNewlines).processingWhitespaces() - return SVGText(text: trimmed, font: font, fill: SVGHelper.parseFill(context.styles, context.index), stroke: SVGHelper.parseStroke(context.styles, index: context.index), textAnchor: textAnchor, transform: transform, shift: shift) + return SVGText(text: trimmed, font: font, fill: SVGHelper.parseFill(context.styles, context.index), stroke: SVGHelper.parseStroke(context.styles, index: context.index), textAnchor: textAnchor, transform: transform, shift: shift, textAnchorString: context.style("text-anchor")) } return SVGGroup(contents: parseContents(context: context, delegate: delegate)) //return .none From ddc7d0c697ed817fdaba3056d7d5324d412bfae5 Mon Sep 17 00:00:00 2001 From: Paco Wong Date: Fri, 28 Jun 2024 11:00:34 +0800 Subject: [PATCH 4/5] Expose the content dx and dy --- Source/Model/Nodes/SVGText.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Model/Nodes/SVGText.swift b/Source/Model/Nodes/SVGText.swift index 76e2832..709d4bc 100644 --- a/Source/Model/Nodes/SVGText.swift +++ b/Source/Model/Nodes/SVGText.swift @@ -3,8 +3,8 @@ import Combine public class SVGText: SVGNode, ObservableObject { public struct Shift: Codable { - let dx: String? - let dy: String? + public let dx: String? + public let dy: String? public static let empty = Shift(dx: nil, dy: nil) } From 184c0d7924a1adfaa87b48aeb08c35d3684d616f Mon Sep 17 00:00:00 2001 From: pacowong Date: Thu, 29 May 2025 21:55:56 +0800 Subject: [PATCH 5/5] Update SVGParser.swift --- Source/Parser/SVG/SVGParser.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Parser/SVG/SVGParser.swift b/Source/Parser/SVG/SVGParser.swift index 53b347f..1656994 100644 --- a/Source/Parser/SVG/SVGParser.swift +++ b/Source/Parser/SVG/SVGParser.swift @@ -70,7 +70,7 @@ public struct SVGParser { private static func parse(context: SVGNodeContext) -> SVGNode? { if context.element.name == "tspan" { - print("[PACO] HELLO") + // TODO: handle differently } return parsers[context.element.name]?.parse(context: context) { parse(element: $0, parentContext: context)