diff --git a/Sources/OpenSwiftUICore/View/Text/AttributedString/Text+AttributedString.swift b/Sources/OpenSwiftUICore/View/Text/AttributedString/Text+AttributedString.swift index 745141531..d39c647bd 100644 --- a/Sources/OpenSwiftUICore/View/Text/AttributedString/Text+AttributedString.swift +++ b/Sources/OpenSwiftUICore/View/Text/AttributedString/Text+AttributedString.swift @@ -714,35 +714,3 @@ extension Dictionary where Key == NSAttributedString.Key, Value == Any { #endif } } - -// FIXME -@available(OpenSwiftUI_v1_0, *) -extension Text { - package struct Superscript: Hashable, Sendable { - package static let `default`: Text.Superscript = .init(0) - - package var value: Int - - package init(_ value: Int) { - self.value = value - } - } - - @_spi(Private) - @available(OpenSwiftUI_v5_0, *) - public struct CustomAttributes: @unchecked Sendable, Hashable { - public init() {} - - package var attributes: [TextAttributeModifierBase] = [] - } -} - -package class TextAttributeModifierBase: AnyTextModifier, Hashable { - package static func == (lhs: TextAttributeModifierBase, rhs: TextAttributeModifierBase) -> Bool { - lhs === rhs - } - - package func hash(into hasher: inout Hasher) { - _openSwiftUIUnimplementedWarning() - } -} diff --git a/Sources/OpenSwiftUICore/View/Text/Text/Text+Renderer.swift b/Sources/OpenSwiftUICore/View/Text/Text/Text+Renderer.swift index 99e5ff63f..8229d3bc2 100644 --- a/Sources/OpenSwiftUICore/View/Text/Text/Text+Renderer.swift +++ b/Sources/OpenSwiftUICore/View/Text/Text/Text+Renderer.swift @@ -3,7 +3,7 @@ // OpenSwiftUICore // // Audited for 6.5.4 -// Status: Empty +// Status: WIP // ID: 7F70C8A76EE0356881289646072938C0 (SwiftUICore) #if canImport(CoreText) @@ -13,7 +13,7 @@ import OpenAttributeGraphShims public import OpenCoreGraphicsShims import UIFoundation_Private -// TODO +// TODO: TextRenderer /// A proxy for a text view that custom text renderers use. @available(OpenSwiftUI_v6_0, *) @@ -32,9 +32,96 @@ public struct TextProxy { } } +// TODO: View + textRenderer + +// MARK: - TextAttribute + /// A value that you can attach to text views and that text renderers can query. @available(OpenSwiftUI_v5_0, *) -public protocol TextAttribute {} +public protocol TextAttribute: Hashable {} + +// MARK: - Text + customAttribute + +@available(OpenSwiftUI_v5_0, *) +extension Text { + /// Adds a custom attribute to the text view. + /// + /// Only one attribute of each type may be attached to each text + /// view, with inner attributes taking precedence. + /// + /// - Parameter value: The attribute to attach. + /// + /// - Returns: A version of the text view with `value` attached. + public func customAttribute(_ value: T) -> Text where T: TextAttribute { + modified(with: .anyTextModifier(TextAttributeModifier(value: value))) + } +} + +// MARK: - TextAttributeModifierBase + +package class TextAttributeModifierBase: AnyTextModifier, Hashable { + package func hash(into hasher: inout Hasher) { + _openSwiftUIBaseClassAbstractMethod() + } + + package static func == (lhs: TextAttributeModifierBase, rhs: TextAttributeModifierBase) -> Bool { + lhs.isEqual(to: rhs) + } +} + +// MARK: - TextAttributeModifier + +private final class TextAttributeModifier: TextAttributeModifierBase where Value: TextAttribute { + let attribute: Value + + init(value: Value) { + attribute = value + } + + override func modify(style: inout Text.Style, environment: EnvironmentValues) { + style.customAttributes.append(self) + } + + override func isEqual(to other: AnyTextModifier) -> Bool { + guard let other = other as? TextAttributeModifier else { + return false + } + return attribute == other.attribute + } + + override package func hash(into hasher: inout Hasher) { + attribute.hash(into: &hasher) + } +} + +// MARK: Text + CustomAttributes + +@_spi(Private) +@available(OpenSwiftUI_v5_0, *) +extension Text { + public struct CustomAttributes: @unchecked Sendable, Hashable { + var attributes: [TextAttributeModifierBase] = [] + + public init() { + _openSwiftUIEmptyStub() + } + + public mutating func add(_ value: T) where T: TextAttribute { + attributes.append(TextAttributeModifier(value: value)) + } + + public subscript(_ key: T.Type) -> T? where T: TextAttribute { + for attribute in attributes { + if let modifier = attribute as? TextAttributeModifier { + return modifier.attribute + } + } + return nil + } + } +} + +// TODO: _TextRendererViewModifier // MARK: - TextRendererBoxBase diff --git a/Sources/OpenSwiftUICore/View/Text/Text/Text+Superscript.swift b/Sources/OpenSwiftUICore/View/Text/Text/Text+Superscript.swift new file mode 100644 index 000000000..1ae0e7b74 --- /dev/null +++ b/Sources/OpenSwiftUICore/View/Text/Text/Text+Superscript.swift @@ -0,0 +1,12 @@ +// +// Text+Superscript.swift +// OpenSwiftUICore +// +// Audited for 6.5.4 +// Status: Complete + +extension Text { + package struct Superscript: Sendable, Hashable { + package static let `default`: Text.Superscript = .init() + } +}