Skip to content
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
23 changes: 18 additions & 5 deletions Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
remoteGlobalIDString = 275751E22DEE1441003E467C;
remoteInfo = TestingHost;
};
27DC9A772F2017EA00F8F371 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 27CD0B412AFC8D37003665EB /* Project object */;
proxyType = 1;
remoteGlobalIDString = 27D49DF72BA604FB00F6E2E2;
remoteInfo = HostingExample;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -233,6 +240,7 @@
);
dependencies = (
279080A42E8E600A0082B5B6 /* PBXTargetDependency */,
27DC9A782F2017EA00F8F371 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
275751F62DEE1456003E467C /* OpenSwiftUIUITests */,
Expand Down Expand Up @@ -310,7 +318,7 @@
};
279283B82DFF11CE00234D64 = {
CreatedOnToolsVersion = 16.3;
TestTargetID = 275751E22DEE1441003E467C;
TestTargetID = 27D49DF72BA604FB00F6E2E2;
};
27CD0B482AFC8D37003665EB = {
CreatedOnToolsVersion = 15.0;
Expand Down Expand Up @@ -414,6 +422,11 @@
target = 275751E22DEE1441003E467C /* TestingHost */;
targetProxy = 279080A32E8E600A0082B5B6 /* PBXContainerItemProxy */;
};
27DC9A782F2017EA00F8F371 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 27D49DF72BA604FB00F6E2E2 /* HostingExample */;
targetProxy = 27DC9A772F2017EA00F8F371 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
Expand Down Expand Up @@ -1103,7 +1116,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestingHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TestingHost";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HostingExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/HostingExample";
};
name = SwiftUIDebug;
};
Expand All @@ -1125,7 +1138,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestingHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TestingHost";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HostingExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/HostingExample";
};
name = SwiftUIRelease;
};
Expand All @@ -1147,7 +1160,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestingHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TestingHost";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HostingExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/HostingExample";
};
name = OpenSwiftUIDebug;
};
Expand All @@ -1169,7 +1182,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestingHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TestingHost";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HostingExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/HostingExample";
};
name = OpenSwiftUIRelease;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// BlurEffectUITests.swift
// OpenSwiftUIUITests

import Testing
import SnapshotTesting

@MainActor
@Suite(.snapshots(record: .never, diffTool: diffTool))
struct BlurEffectUITests {
@Test
func blurColor() {
struct ContentView: View {
var body: some View {
Color.blue
.frame(width: 100, height: 100)
.blur(radius: 10)
.background(Color.red)
}
}
openSwiftUIAssertSnapshot(of: ContentView(), drawHierarchyInKeyWindow: true)
}

// TODO: blur image test when named image is supported
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let defaultSize = CGSize(width: 200, height: 200)

func openSwiftUIAssertSnapshot<V: View>(
of value: @autoclosure () -> V,
drawHierarchyInKeyWindow: Bool = false,
perceptualPrecision: Float = 1,
size: CGSize = defaultSize,
named name: String? = nil,
Expand All @@ -51,7 +52,7 @@ func openSwiftUIAssertSnapshot<V: View>(
) {
openSwiftUIAssertSnapshot(
of: PlatformHostingController(rootView: value()),
as: .image(perceptualPrecision: perceptualPrecision, size: size),
as: .image(drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, perceptualPrecision: perceptualPrecision, size: size),
named: (name.map { ".\($0)" } ?? "") + "\(Int(size.width))x\(Int(size.height))",
record: recording,
timeout: timeout,
Expand Down
4 changes: 4 additions & 0 deletions Example/TestingHost/TestingHostApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// TestingHostApp.swift
// TestingHost

// FIXME: OpenSwiftUI does not set up key window correctly
// -> use HostingExample as OpenSwiftUIUITests's host temporary to add drawHierarchyInKeyWindow support

#if OPENSWIFTUI
import OpenSwiftUI
#else
Expand All @@ -16,6 +19,7 @@ import UIKit

@main
struct TestingHostApp: App {
// FIXME: OpenSwiftUI does not support ApplicationDelegateAdaptor yet
#if !OPENSWIFTUI
#if canImport(AppKit)
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
Expand Down
87 changes: 87 additions & 0 deletions Sources/OpenSwiftUICore/Render/RendererEffect/BlurEffect.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// BlurEffect.swift
// OpenSwiftUICore
//
// Audited for 6.5.4
// Status: Complete

public import Foundation

// MARK: - _BlurEffect

/// A blur effect applied to a view.
@available(OpenSwiftUI_v1_0, *)
@frozen
public struct _BlurEffect: RendererEffect, Equatable {

public var radius: CGFloat

public var isOpaque: Bool

@inlinable
public init(radius: CGFloat, opaque: Bool) {
self.radius = radius
self.isOpaque = opaque
}

public var animatableData: CGFloat {
get { radius }
set { radius = newValue }
}

package var descriptionAttributes: [(name: String, value: String)] {
var attributes: [(name: String, value: String)] = []
attributes.append(("radius", radius.description))
attributes.append(("isOpaque", isOpaque ? "true" : "false"))
return attributes
}

package func effectValue(size: CGSize) -> DisplayList.Effect {
.filter(.blur(BlurStyle(radius: radius, isOpaque: isOpaque)))
}

nonisolated public static func == (a: _BlurEffect, b: _BlurEffect) -> Swift.Bool {
a.radius == b.radius && a.isOpaque == b.isOpaque
}
}

// MARK: - View + blur

@available(OpenSwiftUI_v1_0, *)
extension View {

/// Applies a Gaussian blur to this view.
///
/// Use `blur(radius:opaque:)` to apply a gaussian blur effect to the
/// rendering of this view.
///
/// The example below shows two ``Text`` views, the first with no blur
/// effects, the second with `blur(radius:opaque:)` applied with the
/// `radius` set to `2`. The larger the radius, the more diffuse the
/// effect.
///
/// struct Blur: View {
/// var body: some View {
/// VStack {
/// Text("This is some text.")
/// .padding()
/// Text("This is some blurry text.")
/// .blur(radius: 2.0)
/// }
/// }
/// }
///
/// ![A screenshot showing the effect of applying gaussian blur effect to
/// the rendering of a view.](OpenSwiftUI-View-blurRadius.png)
///
/// - Parameters:
/// - radius: The radial size of the blur. A blur is more diffuse when its
/// radius is large.
/// - opaque: A Boolean value that indicates whether the blur renderer
/// permits transparency in the blur output. Set to `true` to create an
/// opaque blur, or set to `false` to permit transparency.
@inlinable
nonisolated public func blur(radius: CGFloat, opaque: Bool = false) -> some View {
return modifier(_BlurEffect(radius: radius, opaque: opaque))
}
}
Loading