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
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "OPENSWIFTUI_PRINT_TREE"
value = "1"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "SWIFTUI_PRINT_TREE"
value = "1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
value = "1"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "OPENSWIFTUI_PRINT_TREE"
value = "1"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
value = "1"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "OPENSWIFTUI_PRINT_TREE"
value = "1"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
Expand Down
6 changes: 6 additions & 0 deletions Example/Shared/Render/Async/AsyncRenderExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
// GeometryEffectExample.swift
// Shared

#if OPENSWIFTUI
import OpenSwiftUI
#else
import SwiftUI
#endif

struct AsyncRenderExample: View {
@State private var items = [6]

Expand Down
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ extension TimelineSchedule {
) -> AnySequence<Date> {
AnySequence(entries(within: range, mode: mode, limit: limit))
}
}

extension TimelineSchedule {
package func nextEntry(
after date: Date,
mode: TimelineScheduleMode,
limit: UInt?
) -> Date {
entries(from: date, mode: mode)
.lazy
.abort(after: limit)
.first { $0 > date } ?? .distantFuture
}

private func entries(
within range: Range<Date>,
Expand Down
154 changes: 154 additions & 0 deletions Sources/OpenSwiftUICore/Render/DisplayList/DisplayList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ package struct DisplayList: Equatable {
package var isEmpty: Bool {
items.isEmpty
}

// TODO

package func nextUpdate(after time: Time) -> Time {
guard !features.contains(.animations) else {
return time
}
var nextUpdate = Time.infinity
if features.contains(.dynamicContent) {
for item in items {
nextUpdate = min(nextUpdate, item.nextUpdate(after: time))
if nextUpdate == time {
break
}
}
}
return nextUpdate
}
}

@available(*, unavailable)
Expand Down Expand Up @@ -177,6 +195,38 @@ extension DisplayList {
indirect case drawing(any ORBDisplayListContents, CGPoint, RasterizationOptions)
indirect case view(any _DisplayList_ViewFactory)
case placeholder(id: Identity)

@inline(__always)
var caseName: String {
switch self {
case .backdrop:
return "backdrop"
case .color:
return "color"
case .chameleonColor:
return "chameleonColor"
case .image:
return "image"
case .shape:
return "shape"
case .shadow:
return "shadow"
case .platformView:
return "platformView"
case .platformLayer:
return "platformLayer"
case .text:
return "text"
case .flattened:
return "flattened"
case .drawing:
return "drawing"
case .view:
return "view"
case .placeholder:
return "placeholder"
}
}
}

package init(_ value: Content.Value, seed: Seed) {
Expand Down Expand Up @@ -618,6 +668,8 @@ extension DisplayList.Item {
extension DisplayList {
// FIXME
package class InterpolatorGroup {
var maxDuration: Double = .zero

private struct Contents {
var list: DisplayList
var origin: CGPoint
Expand Down Expand Up @@ -664,6 +716,10 @@ extension DisplayList {
[]
}

func nextUpdate(after _: Time) -> Time {
.infinity
}

func rewriteDisplayList(
_ list: inout DisplayList,
time: Attribute<Time>,
Expand All @@ -675,6 +731,104 @@ extension DisplayList {
return false
}
}

package class UnaryInterpolatorGroup: InterpolatorGroup {
var layer: InterpolatorLayer = .init()

var contentsScale: Float = .zero

var rasterizationOptions: RasterizationOptions = .init()

override func nextUpdate(after time: Time) -> Time {
layer.nextUpdate(after: time)
}
}

struct InterpolatorLayer {
struct Contents {
var list: DisplayList = .init()
var origin: CGPoint = .zero
var rbList: (any ORBDisplayListContents)?
var nextTime: Time = .infinity
var numericValue: Float?
}

struct Removed {
var contents: Contents = .init()
var interpolator: ORBDisplayListInterpolator?
var transition: ORBTransition?
var animation: ORBAnimation = .init()
var listener: AnimationListener?
var begin: Time = .zero
var duration: Double = .zero
var phase: Phase = .pending
}

enum Phase {
case pending
case first
case second
case running
}

var contents: Contents = .init()
var removed: [Removed] = []
var time: Time = .zero
var renderer: DisplayList.GraphicsRenderer?
var contentSeed: DisplayList.Seed = .init()
var supportsVFD: Bool = false
var needsUpdate: Bool = false

@inline(__always)
func nextUpdate(after _: Time) -> Time {
removed.isEmpty ? contents.nextTime : time
}
}
}

extension DisplayList.Item {
package func nextUpdate(after time: Time) -> Time {
var nextUpdate = Time.infinity
switch value {
case let .content(content):
switch content.value {
case let .text(text, _):
nextUpdate = min(nextUpdate, text.text.nextUpdate(after: time, equivalentDate: .now, reduceFrequency: false)
)
case let .flattened(list, _, _):
nextUpdate = min(nextUpdate, list.nextUpdate(after: time))
default:
break
}
case let .effect(effect, list):
nextUpdate = min(nextUpdate, list.nextUpdate(after: time))
switch effect {
case let .mask(mask, _):
nextUpdate = min(nextUpdate, mask.nextUpdate(after: time))
case .animation:
nextUpdate = time
case let .interpolatorLayer(group, _):
nextUpdate = min(nextUpdate, group.nextUpdate(after: time))
default:
break
}
case let .states(states):
for (_, list) in states {
let nestedUpdate: Time
if list.features.contains(.animations) {
nestedUpdate = time
} else if list.features.contains(.dynamicContent) {
nestedUpdate = list.nextUpdate(after: time)
} else {
nestedUpdate = .infinity
}
nextUpdate = min(nextUpdate, nestedUpdate)
}
case .empty:
break
}
return nextUpdate
}
}

package struct AccessibilityNodeAttachment {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,124 @@
var isContentGeometryEnabled: Bool {
flags.contains(.contentGeometry)
}

@inline(__always)
mutating func update<P>(
_ property: P.Type,
from oldValue: P.Value,
to newValue: P.Value
) where P: Property, P.Value: Equatable {
guard oldValue != newValue else {
return
}
setValue(P.self, to: newValue)
}

@inline(__always)
mutating func setValue<P>(
_ property: P.Type,
to value: P.Value
) where P: Property {
cache.pointee.setAsyncValue(
P.boxValue(value),
for: P.keyPath,
in: layer,
usingPresentationModifier: P.supportsPresentationModifier
)
}
}

// MARK: - AsyncLayer.Property

struct BackgroundColor: AsyncLayer.Property {
static let keyPath = "backgroundColor"

static func boxValue(_ value: Color.Resolved) -> NSObject {
#if canImport(Darwin)
unsafeDowncast(value.cgColor, to: NSObject.self)
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

struct PositionLayer: AsyncLayer.Property {
static let keyPath = "position"

static func boxValue(_ value: CGPoint) -> NSObject {
#if canImport(QuartzCore)
NSValue(point: value)

Check failure on line 109 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute compatibility tests for iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'point:', expected 'nonretainedObject:')

Check failure on line 109 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute UI tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'point:', expected 'nonretainedObject:')

Check failure on line 109 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute UI tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'point:', expected 'nonretainedObject:')

Check failure on line 109 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'point:', expected 'nonretainedObject:')
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

struct BoundsLayer: AsyncLayer.Property {
static let keyPath = "bounds"

static func boxValue(_ value: CGRect) -> NSObject {
#if canImport(QuartzCore)
NSValue(rect: value)

Check failure on line 121 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute compatibility tests for iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'rect:', expected 'nonretainedObject:')

Check failure on line 121 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute UI tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'rect:', expected 'nonretainedObject:')

Check failure on line 121 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute UI tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'rect:', expected 'nonretainedObject:')

Check failure on line 121 in Sources/OpenSwiftUICore/Render/DisplayList/DisplayListAsyncLayer.swift

View workflow job for this annotation

GitHub Actions / Execute tests on iOS (macos-15, 16.4, 2024, 18.5)

incorrect argument label in call (have 'rect:', expected 'nonretainedObject:')
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

struct AffineTransformLayer: AsyncLayer.Property {
static let keyPath = "transform"

static func boxValue(_ value: CGAffineTransform) -> NSObject {
#if canImport(QuartzCore)
NSValue(caTransform3D: CATransform3DMakeAffineTransform(value))
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

struct LayerProjectionTransform: AsyncLayer.Property {
static let keyPath = "transform"

static func boxValue(_ value: ProjectionTransform) -> NSObject {
#if canImport(QuartzCore)
NSValue(caTransform3D: CATransform3D(value))
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

struct OpacityLayer: AsyncLayer.Property {
static let keyPath = "opacity"

static func boxValue(_ value: Float) -> NSObject {
NSNumber(value: value)
}
}

struct CornerRadiusLayer: AsyncLayer.Property {
static let keyPath = "cornerRadius"

static func boxValue(_ value: CGFloat) -> NSObject {
NSNumber(value: Double(value))
}
}

struct ContentsMultiplyColor: AsyncLayer.Property {
static let keyPath = "contentsMultiplyColor"

static func boxValue(_ value: Color.Resolved?) -> NSObject {
#if canImport(Darwin)
guard let value else {
return NSNull()
}
return unsafeDowncast(value.cgColor, to: NSObject.self)
#else
_openSwiftUIPlatformUnimplementedFailure()
#endif
}
}

}
Loading
Loading