Skip to content

Commit e92302a

Browse files
authored
Merge pull request #30 from swhitty/preserve-all-sfsymbol-classes
Preserve all SFSymbol classes
2 parents 6b176b5 + 1f981b3 commit e92302a

File tree

5 files changed

+94
-8
lines changed

5 files changed

+94
-8
lines changed

Samples.bundle/checkmark.svg

Lines changed: 19 additions & 0 deletions
Loading

SwiftDraw/Parser.XML.Color.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ extension XMLParser {
5555
}
5656

5757
private func parseColorNone(data: String) -> DOM.Color? {
58-
if data.trimmingCharacters(in: .whitespaces) == "none" {
58+
let trimmed = data.trimmingCharacters(in: .whitespaces)
59+
if trimmed == "none" || trimmed == "transparent" {
5960
return DOM.Color.none // .none resolves to Optional.none
6061
}
6162
return nil

SwiftDraw/Renderer.SFSymbol.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ extension SFSymbolRenderer {
126126
case black
127127
}
128128

129-
130129
func getInsets(for variant: Variant) -> CommandLine.Insets {
131130
switch variant {
132131
case .regular:
@@ -177,7 +176,8 @@ extension SFSymbolRenderer {
177176
static func getSymbolPaths(for layer: LayerTree.Layer,
178177
ctm: LayerTree.Transform.Matrix = .identity) -> [SymbolPath] {
179178

180-
guard layer.opacity > 0 else { return [] }
179+
let isSFSymbolLayer = containsAcceptedName(layer.class)
180+
guard isSFSymbolLayer || layer.opacity > 0 else { return [] }
181181
guard layer.clip.isEmpty else {
182182
print("Warning:", "clip-path unsupported in SF Symbols.", to: &.standardError)
183183
return []
@@ -190,12 +190,15 @@ extension SFSymbolRenderer {
190190
let ctm = ctm.concatenated(layer.transform.toMatrix())
191191
var paths = [SymbolPath]()
192192

193-
let symbolClass = containsAcceptedName(layer.class) ? layer.class : nil
193+
let symbolClass = isSFSymbolLayer ? layer.class : nil
194194

195195
for c in layer.contents {
196196
switch c {
197197
case let .shape(shape, stroke, fill):
198-
if let path = makePath(for: shape, stoke: stroke, fill: fill)?.applying(matrix: ctm) {
198+
if let path = makePath(for: shape,
199+
stoke: stroke,
200+
fill: fill,
201+
preserve: isSFSymbolLayer)?.applying(matrix: ctm) {
199202
if fill.rule == .evenodd {
200203
paths.append(SymbolPath(class: symbolClass, path: path.makeNonZero()))
201204
} else {
@@ -218,13 +221,14 @@ extension SFSymbolRenderer {
218221

219222
static func makePath(for shape: LayerTree.Shape,
220223
stoke: LayerTree.StrokeAttributes,
221-
fill: LayerTree.FillAttributes) -> LayerTree.Path? {
224+
fill: LayerTree.FillAttributes,
225+
preserve: Bool) -> LayerTree.Path? {
222226

223-
if fill.fill != .none && fill.opacity > 0 {
227+
if preserve || (fill.fill != .none && fill.opacity > 0) {
224228
return shape.path
225229
}
226230

227-
if stoke.color != .none && stoke.width > 0 {
231+
if preserve || (stoke.color != .none && stoke.width > 0) {
228232
#if canImport(CoreGraphics)
229233
return expandOutlines(for: shape.path, stroke: stoke)
230234
#else

SwiftDrawTests/Parser.XML.ColorTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ final class ParserColorTests: XCTestCase {
4040
XCTAssertEqual(try XMLParser().parseColor("\t none \t"), .none)
4141
}
4242

43+
func testColorTransparent() {
44+
XCTAssertEqual(try XMLParser().parseColor("transparent"), .none)
45+
XCTAssertEqual(try XMLParser().parseColor(" transparent"), .none)
46+
XCTAssertEqual(try XMLParser().parseColor("\t transparent \t"), .none)
47+
}
48+
4349
func testColorCurrent() {
4450
XCTAssertEqual(try XMLParser().parseColor("currentColor"), .currentColor)
4551
XCTAssertEqual(try XMLParser().parseColor(" currentColor"), .currentColor)

SwiftDrawTests/Renderer.SFSymbolTests.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,62 @@ final class RendererSFSymbolTests: XCTestCase {
7272

7373
}
7474

75+
func testTransparentLayers_Are_Removed() throws {
76+
let source = try DOM.SVG.parse(#"""
77+
<?xml version="1.0" encoding="UTF-8"?>
78+
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg">
79+
<rect width="100" height="100" fill="currentColor" />
80+
<rect width="100" height="100" fill="transparent" />
81+
<rect width="100" height="100" fill="currentColor" opacity="0" />
82+
</svg>
83+
"""#)
84+
85+
let template = try SFSymbolTemplate.parse(
86+
SFSymbolRenderer.render(svg: source)
87+
)
88+
89+
XCTAssertEqual(
90+
template.ultralight.contents.paths.count,
91+
1
92+
)
93+
XCTAssertEqual(
94+
template.regular.contents.paths.count,
95+
1
96+
)
97+
XCTAssertEqual(
98+
template.black.contents.paths.count,
99+
1
100+
)
101+
}
102+
103+
func testTransparentSFSymboleLayers_AreNot_Removed() throws {
104+
let source = try DOM.SVG.parse(#"""
105+
<?xml version="1.0" encoding="UTF-8"?>
106+
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg">
107+
<rect width="100" height="100" fill="currentColor" />
108+
<rect width="100" height="100" fill="transparent" class="multicolor-0:custom" />
109+
<rect width="100" height="100" fill="currentColor" opacity="0" class="SFSymbolsPreview" />
110+
</svg>
111+
"""#)
112+
113+
let template = try SFSymbolTemplate.parse(
114+
SFSymbolRenderer.render(svg: source)
115+
)
116+
117+
XCTAssertEqual(
118+
template.ultralight.contents.paths.count,
119+
3
120+
)
121+
XCTAssertEqual(
122+
template.regular.contents.paths.count,
123+
3
124+
)
125+
XCTAssertEqual(
126+
template.black.contents.paths.count,
127+
3
128+
)
129+
}
130+
75131
#if canImport(CoreGraphics)
76132
func testStrokeSymbol() throws {
77133
let url = try Bundle.test.url(forResource: "key.svg")

0 commit comments

Comments
 (0)