Skip to content

Commit 8abb043

Browse files
authored
Merge pull request #61 from swhitty/clips-path
Clips Path should preserve transforms
2 parents 7429012 + 7376d39 commit 8abb043

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: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,15 +311,21 @@ 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 { clip in
317+
if clip.transform == .identity {
318+
return provider.createPath(from: clip.shape)
319+
} else {
320+
return provider.createPath(from: .path(clip.shape.path.applying(matrix: clip.transform)))
321+
}
322+
}
318323
let clipPath = provider.createPath(from: paths)
319324
let rule = provider.createFillRule(from: rule ?? .nonzero)
320325
return [.setClip(path: clipPath, rule: rule)]
321326
}
322327

328+
323329
func renderCommands(forMask layer: Layer?) -> [RendererCommand<P.Types>] {
324330
guard let layer = layer else { return [] }
325331

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ 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+
}
4146
}
4247

4348
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, transform: .identity) }, using: rule)
78+
}
79+
}

0 commit comments

Comments
 (0)