Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clips Path should preserve transforms #61

Merged
merged 3 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Samples.bundle/alert.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 14 additions & 3 deletions SwiftDraw/LayerTree.Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
guard state.display != .none else { return l }

l.transform = Builder.createTransforms(from: attributes.transform ?? [])
l.clip = createClipShapes(for: element)
l.clip = makeClipShapes(for: element)
l.clipRule = attributes.clipRule
l.mask = createMaskLayer(for: element)
l.opacity = state.opacity
Expand Down Expand Up @@ -123,11 +123,22 @@
return nil
}

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

return clip.childElements.compactMap{ Builder.makeShape(from: $0) }
return clip.childElements.compactMap(makeClipShape)
}

func makeClipShape(for element: DOM.GraphicsElement) -> ClipShape? {
guard let shape = Builder.makeShape(from: element) else {
return nil

Check warning on line 135 in SwiftDraw/LayerTree.Builder.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/LayerTree.Builder.swift#L135

Added line #L135 was not covered by tests
}

let transform = Self.createTransforms(from: element.attributes.transform ?? [])
.toMatrix()

return ClipShape(shape: shape, transform: transform)
}

func createMaskLayer(for element: DOM.GraphicsElement) -> Layer? {
Expand Down
12 changes: 9 additions & 3 deletions SwiftDraw/LayerTree.CommandGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,15 +311,21 @@
}
}

func renderCommands(forClip shapes: [Shape], using rule: FillRule?) -> [RendererCommand<P.Types>] {
func renderCommands(forClip shapes: [ClipShape], using rule: FillRule?) -> [RendererCommand<P.Types>] {
guard !shapes.isEmpty else { return [] }

let paths = shapes.map { provider.createPath(from: $0) }
let paths = shapes.map { clip in
if clip.transform == .identity {
return provider.createPath(from: clip.shape)
} else {
return provider.createPath(from: .path(clip.shape.path.applying(matrix: clip.transform)))
}

Check warning on line 321 in SwiftDraw/LayerTree.CommandGenerator.swift

View check run for this annotation

Codecov / codecov/patch

SwiftDraw/LayerTree.CommandGenerator.swift#L320-L321

Added lines #L320 - L321 were not covered by tests
}
let clipPath = provider.createPath(from: paths)
let rule = provider.createFillRule(from: rule ?? .nonzero)
return [.setClip(path: clipPath, rule: rule)]
}


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

Expand Down
2 changes: 1 addition & 1 deletion SwiftDraw/LayerTree.Layer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension LayerTree {
var contents: [Contents] = []
var opacity: Float = 1.0
var transform: [Transform] = []
var clip: [Shape] = []
var clip: [ClipShape] = []
var clipRule: FillRule?
var mask: Layer?
var filters: [Filter] = []
Expand Down
5 changes: 5 additions & 0 deletions SwiftDraw/LayerTree.Shape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ extension LayerTree {
case polygon(between: [Point])
case path(Path)
}

struct ClipShape: Hashable {
var shape: Shape
var transform: Transform.Matrix
}
}

extension LayerTree.Shape {
Expand Down
5 changes: 5 additions & 0 deletions SwiftDrawTests/LayerTree.BuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,9 @@ private extension LayerTree.Builder {
let builder = LayerTree.Builder(svg: DOM.SVG(width: 10, height: 10))
return builder.makeStrokeAttributes(with: state)
}

func createClipShapes(for element: DOM.GraphicsElement) -> [LayerTree.Shape] {
makeClipShapes(for: element).map(\.shape)
}
}

7 changes: 7 additions & 0 deletions SwiftDrawTests/LayerTree.CommandGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,10 @@ final class LayerTreeCommandGeneratorTests: XCTestCase {
XCTAssertEqual(commands.count, 4)
}
}

private extension LayerTree.CommandGenerator {

func renderCommands(forClip shapes: [LayerTree.Shape], using rule: LayerTree.FillRule?) -> [RendererCommand<P.Types>] {
renderCommands(forClip: shapes.map { LayerTree.ClipShape(shape: $0, transform: .identity) }, using: rule)
}
}