From 4200c3fe7521c21dbdc027f8d59de80392aa4a20 Mon Sep 17 00:00:00 2001 From: Simon Whitty Date: Sun, 22 Oct 2023 10:27:12 +1100 Subject: [PATCH 1/4] Support color: transparent --- SwiftDraw/Parser.XML.Color.swift | 3 ++- SwiftDrawTests/Parser.XML.ColorTests.swift | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/SwiftDraw/Parser.XML.Color.swift b/SwiftDraw/Parser.XML.Color.swift index eeb283f..cbc1e39 100644 --- a/SwiftDraw/Parser.XML.Color.swift +++ b/SwiftDraw/Parser.XML.Color.swift @@ -55,7 +55,8 @@ extension XMLParser { } private func parseColorNone(data: String) -> DOM.Color? { - if data.trimmingCharacters(in: .whitespaces) == "none" { + let trimmed = data.trimmingCharacters(in: .whitespaces) + if trimmed == "none" || trimmed == "transparent" { return DOM.Color.none // .none resolves to Optional.none } return nil diff --git a/SwiftDrawTests/Parser.XML.ColorTests.swift b/SwiftDrawTests/Parser.XML.ColorTests.swift index da2006c..f258e7f 100644 --- a/SwiftDrawTests/Parser.XML.ColorTests.swift +++ b/SwiftDrawTests/Parser.XML.ColorTests.swift @@ -40,6 +40,12 @@ final class ParserColorTests: XCTestCase { XCTAssertEqual(try XMLParser().parseColor("\t none \t"), .none) } + func testColorTransparent() { + XCTAssertEqual(try XMLParser().parseColor("transparent"), .none) + XCTAssertEqual(try XMLParser().parseColor(" transparent"), .none) + XCTAssertEqual(try XMLParser().parseColor("\t transparent \t"), .none) + } + func testColorCurrent() { XCTAssertEqual(try XMLParser().parseColor("currentColor"), .currentColor) XCTAssertEqual(try XMLParser().parseColor(" currentColor"), .currentColor) From 4e70266dee0ddbc18753c3fada48aa12157e5cb8 Mon Sep 17 00:00:00 2001 From: Simon Whitty Date: Sun, 22 Oct 2023 10:27:43 +1100 Subject: [PATCH 2/4] Preserve all layers marked with SFSymbol classes --- SwiftDraw/Renderer.SFSymbol.swift | 20 +++++--- SwiftDrawTests/Renderer.SFSymbolTests.swift | 56 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/SwiftDraw/Renderer.SFSymbol.swift b/SwiftDraw/Renderer.SFSymbol.swift index f669c20..d8acbab 100644 --- a/SwiftDraw/Renderer.SFSymbol.swift +++ b/SwiftDraw/Renderer.SFSymbol.swift @@ -126,7 +126,6 @@ extension SFSymbolRenderer { case black } - func getInsets(for variant: Variant) -> CommandLine.Insets { switch variant { case .regular: @@ -177,7 +176,8 @@ extension SFSymbolRenderer { static func getSymbolPaths(for layer: LayerTree.Layer, ctm: LayerTree.Transform.Matrix = .identity) -> [SymbolPath] { - guard layer.opacity > 0 else { return [] } + let isSFSymbolLayer = containsAcceptedName(layer.class) + guard isSFSymbolLayer || layer.opacity > 0 else { return [] } guard layer.clip.isEmpty else { print("Warning:", "clip-path unsupported in SF Symbols.", to: &.standardError) return [] @@ -190,17 +190,22 @@ extension SFSymbolRenderer { let ctm = ctm.concatenated(layer.transform.toMatrix()) var paths = [SymbolPath]() - let symbolClass = containsAcceptedName(layer.class) ? layer.class : nil + let symbolClass = isSFSymbolLayer ? layer.class : nil for c in layer.contents { switch c { case let .shape(shape, stroke, fill): - if let path = makePath(for: shape, stoke: stroke, fill: fill)?.applying(matrix: ctm) { + if let path = makePath(for: shape, + stoke: stroke, + fill: fill, + preserve: isSFSymbolLayer)?.applying(matrix: ctm) { if fill.rule == .evenodd { paths.append(SymbolPath(class: symbolClass, path: path.makeNonZero())) } else { paths.append(SymbolPath(class: symbolClass, path: path)) } + } else { + print("skippibng") } case let .text(text, point, attributes): if let path = makePath(for: text, at: point, with: attributes) { @@ -218,13 +223,14 @@ extension SFSymbolRenderer { static func makePath(for shape: LayerTree.Shape, stoke: LayerTree.StrokeAttributes, - fill: LayerTree.FillAttributes) -> LayerTree.Path? { + fill: LayerTree.FillAttributes, + preserve: Bool) -> LayerTree.Path? { - if fill.fill != .none && fill.opacity > 0 { + if preserve || (fill.fill != .none && fill.opacity > 0) { return shape.path } - if stoke.color != .none && stoke.width > 0 { + if preserve || (stoke.color != .none && stoke.width > 0) { #if canImport(CoreGraphics) return expandOutlines(for: shape.path, stroke: stoke) #else diff --git a/SwiftDrawTests/Renderer.SFSymbolTests.swift b/SwiftDrawTests/Renderer.SFSymbolTests.swift index df50d09..7ee254f 100644 --- a/SwiftDrawTests/Renderer.SFSymbolTests.swift +++ b/SwiftDrawTests/Renderer.SFSymbolTests.swift @@ -72,6 +72,62 @@ final class RendererSFSymbolTests: XCTestCase { } + func testTransparentLayers_Are_Removed() throws { + let source = try DOM.SVG.parse(#""" + + + + + + + """#) + + let template = try SFSymbolTemplate.parse( + SFSymbolRenderer.render(svg: source) + ) + + XCTAssertEqual( + template.ultralight.contents.paths.count, + 1 + ) + XCTAssertEqual( + template.regular.contents.paths.count, + 1 + ) + XCTAssertEqual( + template.black.contents.paths.count, + 1 + ) + } + + func testTransparentSFSymboleLayers_AreNot_Removed() throws { + let source = try DOM.SVG.parse(#""" + + + + + + + """#) + + let template = try SFSymbolTemplate.parse( + SFSymbolRenderer.render(svg: source) + ) + + XCTAssertEqual( + template.ultralight.contents.paths.count, + 3 + ) + XCTAssertEqual( + template.regular.contents.paths.count, + 3 + ) + XCTAssertEqual( + template.black.contents.paths.count, + 3 + ) + } + #if canImport(CoreGraphics) func testStrokeSymbol() throws { let url = try Bundle.test.url(forResource: "key.svg") From dc1a083a28cacaf198ad64411eea1a63f7a6abb4 Mon Sep 17 00:00:00 2001 From: Simon Whitty Date: Sun, 22 Oct 2023 10:35:47 +1100 Subject: [PATCH 3/4] sample checkmark --- Samples.bundle/checkmark.svg | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Samples.bundle/checkmark.svg diff --git a/Samples.bundle/checkmark.svg b/Samples.bundle/checkmark.svg new file mode 100644 index 0000000..22a4a4f --- /dev/null +++ b/Samples.bundle/checkmark.svg @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file From 1f981b33785be48250bfff06b0b1985f2cd5ca86 Mon Sep 17 00:00:00 2001 From: Simon Whitty Date: Sun, 22 Oct 2023 10:43:57 +1100 Subject: [PATCH 4/4] remove debug code --- SwiftDraw/Renderer.SFSymbol.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/SwiftDraw/Renderer.SFSymbol.swift b/SwiftDraw/Renderer.SFSymbol.swift index d8acbab..b05d9c6 100644 --- a/SwiftDraw/Renderer.SFSymbol.swift +++ b/SwiftDraw/Renderer.SFSymbol.swift @@ -204,8 +204,6 @@ extension SFSymbolRenderer { } else { paths.append(SymbolPath(class: symbolClass, path: path)) } - } else { - print("skippibng") } case let .text(text, point, attributes): if let path = makePath(for: text, at: point, with: attributes) {