Skip to content

Commit

Permalink
Add ClipEffect interface (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle-Ye committed Jun 27, 2024
1 parent f4d379f commit 0f91969
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
130 changes: 130 additions & 0 deletions Sources/OpenSwiftUI/View/Modifier/ClipEffect.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import Foundation

// MARK: - ClipEffect

@frozen
public struct _ClipEffect<ClipShape> where ClipShape: Shape {
public var shape: ClipShape
public var style: FillStyle

@inlinable
public init(shape: ClipShape, style: FillStyle = FillStyle()) {
self.shape = shape
self.style = style
}

public var animatableData: ClipShape.AnimatableData {
get { shape.animatableData }
set { shape.animatableData = newValue }
}

public typealias AnimatableData = ClipShape.AnimatableData
public typealias Body = Swift.Never
}

// FIXME
extension _ClipEffect: PrimitiveViewModifier {}

// MARK: - View Extension

extension View {

/// Sets a clipping shape for this view.
///
/// Use `clipShape(_:style:)` to clip the view to the provided shape. By
/// applying a clipping shape to a view, you preserve the parts of the view
/// covered by the shape, while eliminating other parts of the view. The
/// clipping shape itself isn't visible.
///
/// For example, this code applies a circular clipping shape to a `Text`
/// view:
///
/// Text("Clipped text in a circle")
/// .frame(width: 175, height: 100)
/// .foregroundColor(Color.white)
/// .background(Color.black)
/// .clipShape(Circle())
///
/// The resulting view shows only the portion of the text that lies within
/// the bounds of the circle.
///
/// ![A screenshot of text clipped to the shape of a
/// circle.](OpenSwiftUI-View-clipShape.png)
///
/// - Parameters:
/// - shape: The clipping shape to use for this view. The `shape` fills
/// the view's frame, while maintaining its aspect ratio.
/// - style: The fill style to use when rasterizing `shape`.
///
/// - Returns: A view that clips this view to `shape`, using `style` to
/// define the shape's rasterization.
@inlinable
public func clipShape<S>(_ shape: S, style: FillStyle = FillStyle()) -> some View where S: Shape {
modifier(_ClipEffect(shape: shape, style: style))
}


/// Clips this view to its bounding rectangular frame.
///
/// Use the `clipped(antialiased:)` modifier to hide any content that
/// extends beyond the layout bounds of the shape.
///
/// By default, a view's bounding frame is used only for layout, so any
/// content that extends beyond the edges of the frame is still visible.
///
/// Text("This long text string is clipped")
/// .fixedSize()
/// .frame(width: 175, height: 100)
/// .clipped()
/// .border(Color.gray)
///
/// ![Screenshot showing text clipped to its
/// frame.](OpenSwiftUI-View-clipped.png)
///
/// - Parameter antialiased: A Boolean value that indicates whether the
/// rendering system applies smoothing to the edges of the clipping
/// rectangle.
///
/// - Returns: A view that clips this view to its bounding frame.
@inlinable
public func clipped(antialiased: Bool = false) -> some View {
clipShape(
Rectangle(),
style: FillStyle(antialiased: antialiased)
)
}


/// Clips this view to its bounding frame, with the specified corner radius.
///
/// By default, a view's bounding frame only affects its layout, so any
/// content that extends beyond the edges of the frame remains visible. Use
/// `cornerRadius(_:antialiased:)` to hide any content that extends beyond
/// these edges while applying a corner radius.
///
/// The following code applies a corner radius of 25 to a text view:
///
/// Text("Rounded Corners")
/// .frame(width: 175, height: 75)
/// .foregroundColor(Color.white)
/// .background(Color.black)
/// .cornerRadius(25)
///
/// ![A screenshot of a rectangle with rounded corners bounding a text
/// view.](OpenSwiftUI-View-cornerRadius.png)
///
/// - Parameter antialiased: A Boolean value that indicates whether the
/// rendering system applies smoothing to the edges of the clipping
/// rectangle.
///
/// - Returns: A view that clips this view to its bounding frame with the
/// specified corner radius.
@available(*, deprecated, message: "Use `clipShape` or `fill` instead.")
@inlinable
public func cornerRadius(_ radius: CGFloat, antialiased: Bool = true) -> some View {
clipShape(
RoundedRectangle(cornerRadius: radius),
style: FillStyle(antialiased: antialiased)
)
}
}
18 changes: 18 additions & 0 deletions Sources/OpenSwiftUI/View/Shape/RoundedCornerStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// ShapeRole.swift
// OpenSwiftUI
//
// Audited for RELEASE_2021
// Status: Complete

/// Defines the shape of a rounded rectangle's corners.
public enum RoundedCornerStyle: Sendable {
/// Quarter-circle rounded rect corners.
case circular

/// Continuous curvature rounded rect corners.
case continuous
}

extension RoundedCornerStyle: Equatable {}
extension RoundedCornerStyle: Hashable {}
30 changes: 30 additions & 0 deletions Sources/OpenSwiftUI/View/Shape/RoundedRectangle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Foundation

@frozen
public struct RoundedRectangle: Shape {
public var cornerSize: CGSize
public var style: RoundedCornerStyle

@inlinable
public init(cornerSize: CGSize, style: RoundedCornerStyle = .circular) {
self.cornerSize = cornerSize
self.style = style
}

@inlinable
public init(cornerRadius: CGFloat, style: RoundedCornerStyle = .circular) {
let cornerSize = CGSize(width: cornerRadius, height: cornerRadius)
self.init(cornerSize: cornerSize, style: style)
}

public func path(in rect: CGRect) -> Path {
fatalError("TODO")
}
public var animatableData: CGSize.AnimatableData {
get { cornerSize.animatableData }
set { cornerSize.animatableData = newValue }
}

public typealias Body = _ShapeView<RoundedRectangle, ForegroundStyle>
}

1 change: 1 addition & 0 deletions Sources/OpenSwiftUI/View/Shape/StrokeStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Audited for RELEASE_2021
// Status: Complete

import Foundation
#if canImport(CoreGraphics)
import CoreGraphics
#else
Expand Down

0 comments on commit 0f91969

Please sign in to comment.