Skip to content

Commit 0f91969

Browse files
authored
Add ClipEffect interface (#98)
1 parent f4d379f commit 0f91969

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import Foundation
2+
3+
// MARK: - ClipEffect
4+
5+
@frozen
6+
public struct _ClipEffect<ClipShape> where ClipShape: Shape {
7+
public var shape: ClipShape
8+
public var style: FillStyle
9+
10+
@inlinable
11+
public init(shape: ClipShape, style: FillStyle = FillStyle()) {
12+
self.shape = shape
13+
self.style = style
14+
}
15+
16+
public var animatableData: ClipShape.AnimatableData {
17+
get { shape.animatableData }
18+
set { shape.animatableData = newValue }
19+
}
20+
21+
public typealias AnimatableData = ClipShape.AnimatableData
22+
public typealias Body = Swift.Never
23+
}
24+
25+
// FIXME
26+
extension _ClipEffect: PrimitiveViewModifier {}
27+
28+
// MARK: - View Extension
29+
30+
extension View {
31+
32+
/// Sets a clipping shape for this view.
33+
///
34+
/// Use `clipShape(_:style:)` to clip the view to the provided shape. By
35+
/// applying a clipping shape to a view, you preserve the parts of the view
36+
/// covered by the shape, while eliminating other parts of the view. The
37+
/// clipping shape itself isn't visible.
38+
///
39+
/// For example, this code applies a circular clipping shape to a `Text`
40+
/// view:
41+
///
42+
/// Text("Clipped text in a circle")
43+
/// .frame(width: 175, height: 100)
44+
/// .foregroundColor(Color.white)
45+
/// .background(Color.black)
46+
/// .clipShape(Circle())
47+
///
48+
/// The resulting view shows only the portion of the text that lies within
49+
/// the bounds of the circle.
50+
///
51+
/// ![A screenshot of text clipped to the shape of a
52+
/// circle.](OpenSwiftUI-View-clipShape.png)
53+
///
54+
/// - Parameters:
55+
/// - shape: The clipping shape to use for this view. The `shape` fills
56+
/// the view's frame, while maintaining its aspect ratio.
57+
/// - style: The fill style to use when rasterizing `shape`.
58+
///
59+
/// - Returns: A view that clips this view to `shape`, using `style` to
60+
/// define the shape's rasterization.
61+
@inlinable
62+
public func clipShape<S>(_ shape: S, style: FillStyle = FillStyle()) -> some View where S: Shape {
63+
modifier(_ClipEffect(shape: shape, style: style))
64+
}
65+
66+
67+
/// Clips this view to its bounding rectangular frame.
68+
///
69+
/// Use the `clipped(antialiased:)` modifier to hide any content that
70+
/// extends beyond the layout bounds of the shape.
71+
///
72+
/// By default, a view's bounding frame is used only for layout, so any
73+
/// content that extends beyond the edges of the frame is still visible.
74+
///
75+
/// Text("This long text string is clipped")
76+
/// .fixedSize()
77+
/// .frame(width: 175, height: 100)
78+
/// .clipped()
79+
/// .border(Color.gray)
80+
///
81+
/// ![Screenshot showing text clipped to its
82+
/// frame.](OpenSwiftUI-View-clipped.png)
83+
///
84+
/// - Parameter antialiased: A Boolean value that indicates whether the
85+
/// rendering system applies smoothing to the edges of the clipping
86+
/// rectangle.
87+
///
88+
/// - Returns: A view that clips this view to its bounding frame.
89+
@inlinable
90+
public func clipped(antialiased: Bool = false) -> some View {
91+
clipShape(
92+
Rectangle(),
93+
style: FillStyle(antialiased: antialiased)
94+
)
95+
}
96+
97+
98+
/// Clips this view to its bounding frame, with the specified corner radius.
99+
///
100+
/// By default, a view's bounding frame only affects its layout, so any
101+
/// content that extends beyond the edges of the frame remains visible. Use
102+
/// `cornerRadius(_:antialiased:)` to hide any content that extends beyond
103+
/// these edges while applying a corner radius.
104+
///
105+
/// The following code applies a corner radius of 25 to a text view:
106+
///
107+
/// Text("Rounded Corners")
108+
/// .frame(width: 175, height: 75)
109+
/// .foregroundColor(Color.white)
110+
/// .background(Color.black)
111+
/// .cornerRadius(25)
112+
///
113+
/// ![A screenshot of a rectangle with rounded corners bounding a text
114+
/// view.](OpenSwiftUI-View-cornerRadius.png)
115+
///
116+
/// - Parameter antialiased: A Boolean value that indicates whether the
117+
/// rendering system applies smoothing to the edges of the clipping
118+
/// rectangle.
119+
///
120+
/// - Returns: A view that clips this view to its bounding frame with the
121+
/// specified corner radius.
122+
@available(*, deprecated, message: "Use `clipShape` or `fill` instead.")
123+
@inlinable
124+
public func cornerRadius(_ radius: CGFloat, antialiased: Bool = true) -> some View {
125+
clipShape(
126+
RoundedRectangle(cornerRadius: radius),
127+
style: FillStyle(antialiased: antialiased)
128+
)
129+
}
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// ShapeRole.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for RELEASE_2021
6+
// Status: Complete
7+
8+
/// Defines the shape of a rounded rectangle's corners.
9+
public enum RoundedCornerStyle: Sendable {
10+
/// Quarter-circle rounded rect corners.
11+
case circular
12+
13+
/// Continuous curvature rounded rect corners.
14+
case continuous
15+
}
16+
17+
extension RoundedCornerStyle: Equatable {}
18+
extension RoundedCornerStyle: Hashable {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Foundation
2+
3+
@frozen
4+
public struct RoundedRectangle: Shape {
5+
public var cornerSize: CGSize
6+
public var style: RoundedCornerStyle
7+
8+
@inlinable
9+
public init(cornerSize: CGSize, style: RoundedCornerStyle = .circular) {
10+
self.cornerSize = cornerSize
11+
self.style = style
12+
}
13+
14+
@inlinable
15+
public init(cornerRadius: CGFloat, style: RoundedCornerStyle = .circular) {
16+
let cornerSize = CGSize(width: cornerRadius, height: cornerRadius)
17+
self.init(cornerSize: cornerSize, style: style)
18+
}
19+
20+
public func path(in rect: CGRect) -> Path {
21+
fatalError("TODO")
22+
}
23+
public var animatableData: CGSize.AnimatableData {
24+
get { cornerSize.animatableData }
25+
set { cornerSize.animatableData = newValue }
26+
}
27+
28+
public typealias Body = _ShapeView<RoundedRectangle, ForegroundStyle>
29+
}
30+

Sources/OpenSwiftUI/View/Shape/StrokeStyle.swift

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Audited for RELEASE_2021
66
// Status: Complete
77

8+
import Foundation
89
#if canImport(CoreGraphics)
910
import CoreGraphics
1011
#else

0 commit comments

Comments
 (0)