Skip to content

Commit 54e2b01

Browse files
committed
Clips Path should preserve transforms
1 parent 7429012 commit 54e2b01

File tree

7 files changed

+51
-7
lines changed

7 files changed

+51
-7
lines changed

Samples.bundle/alert.svg

Lines changed: 10 additions & 0 deletions
Loading

SwiftDraw/LayerTree.Builder.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ extension LayerTree {
8282
guard state.display != .none else { return l }
8383

8484
l.transform = Builder.createTransforms(from: attributes.transform ?? [])
85-
l.clip = createClipShapes(for: element)
85+
l.clip = makeClipShapes(for: element)
8686
l.clipRule = attributes.clipRule
8787
l.mask = createMaskLayer(for: element)
8888
l.opacity = state.opacity
@@ -123,11 +123,22 @@ extension LayerTree {
123123
return nil
124124
}
125125

126-
func createClipShapes(for element: DOM.GraphicsElement) -> [Shape] {
126+
func makeClipShapes(for element: DOM.GraphicsElement) -> [ClipShape] {
127127
guard let clipId = element.attributes.clipPath?.fragmentID,
128128
let clip = svg.defs.clipPaths.first(where: { $0.id == clipId }) else { return [] }
129129

130-
return clip.childElements.compactMap{ Builder.makeShape(from: $0) }
130+
return clip.childElements.compactMap(makeClipShape)
131+
}
132+
133+
func makeClipShape(for element: DOM.GraphicsElement) -> ClipShape? {
134+
guard let shape = Builder.makeShape(from: element) else {
135+
return nil
136+
}
137+
138+
let transform = Self.createTransforms(from: element.attributes.transform ?? [])
139+
.toMatrix()
140+
141+
return ClipShape(shape: shape, transform: transform)
131142
}
132143

133144
func createMaskLayer(for element: DOM.GraphicsElement) -> Layer? {

SwiftDraw/LayerTree.CommandGenerator.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,9 @@ extension LayerTree {
311311
}
312312
}
313313

314-
func renderCommands(forClip shapes: [Shape], using rule: FillRule?) -> [RendererCommand<P.Types>] {
314+
func renderCommands(forClip shapes: [ClipShape], using rule: FillRule?) -> [RendererCommand<P.Types>] {
315315
guard !shapes.isEmpty else { return [] }
316-
317-
let paths = shapes.map { provider.createPath(from: $0) }
316+
let paths = shapes.map { provider.createPath(from: .path($0.makePath())) }
318317
let clipPath = provider.createPath(from: paths)
319318
let rule = provider.createFillRule(from: rule ?? .nonzero)
320319
return [.setClip(path: clipPath, rule: rule)]

SwiftDraw/LayerTree.Layer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extension LayerTree {
3232
var contents: [Contents] = []
3333
var opacity: Float = 1.0
3434
var transform: [Transform] = []
35-
var clip: [Shape] = []
35+
var clip: [ClipShape] = []
3636
var clipRule: FillRule?
3737
var mask: Layer?
3838
var filters: [Filter] = []

SwiftDraw/LayerTree.Shape.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ extension LayerTree {
3838
case polygon(between: [Point])
3939
case path(Path)
4040
}
41+
42+
struct ClipShape: Hashable {
43+
var shape: Shape
44+
var transform: Transform.Matrix?
45+
46+
func makePath() -> LayerTree.Path {
47+
guard let transform else {
48+
return shape.path
49+
}
50+
return shape.path.applying(matrix: transform)
51+
}
52+
}
4153
}
4254

4355
extension LayerTree.Shape {

SwiftDrawTests/LayerTree.BuilderTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,9 @@ private extension LayerTree.Builder {
147147
let builder = LayerTree.Builder(svg: DOM.SVG(width: 10, height: 10))
148148
return builder.makeStrokeAttributes(with: state)
149149
}
150+
151+
func createClipShapes(for element: DOM.GraphicsElement) -> [LayerTree.Shape] {
152+
makeClipShapes(for: element).map(\.shape)
153+
}
150154
}
155+

SwiftDrawTests/LayerTree.CommandGeneratorTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,10 @@ final class LayerTreeCommandGeneratorTests: XCTestCase {
7070
XCTAssertEqual(commands.count, 4)
7171
}
7272
}
73+
74+
private extension LayerTree.CommandGenerator {
75+
76+
func renderCommands(forClip shapes: [LayerTree.Shape], using rule: LayerTree.FillRule?) -> [RendererCommand<P.Types>] {
77+
renderCommands(forClip: shapes.map { LayerTree.ClipShape(shape: $0) }, using: rule)
78+
}
79+
}

0 commit comments

Comments
 (0)