1
+ import Foundation
2
+
3
+ public class AnyColorBox {
4
+ }
5
+
6
+ extension AnyColorBox : Hashable {
7
+ public func hash( into hasher: inout Hasher ) {
8
+ hasher. combine ( ObjectIdentifier ( self ) . hashValue)
9
+ }
10
+ }
11
+
12
+ extension AnyColorBox : Equatable {
13
+ public static func == ( lhs: AnyColorBox , rhs: AnyColorBox ) -> Bool {
14
+ return ObjectIdentifier ( lhs) == ObjectIdentifier ( rhs)
15
+ }
16
+ }
17
+
18
+ public class SystemColorType : AnyColorBox {
19
+ public enum SystemColor : String {
20
+ case clear
21
+ case black
22
+ case white
23
+ case gray
24
+ case red
25
+ case green
26
+ case blue
27
+ case orange
28
+ case yellow
29
+ case pink
30
+ case purple
31
+ case primary
32
+ case secondary
33
+ case accentColor
34
+ }
35
+
36
+ public let value : SystemColor
37
+
38
+ internal init ( value: SystemColorType . SystemColor ) {
39
+ self . value = value
40
+ }
41
+
42
+ public var description : String {
43
+ return value. rawValue
44
+ }
45
+ }
46
+
47
+ public class DisplayP3 : AnyColorBox {
48
+ public let red : Double
49
+ public let green : Double
50
+ public let blue : Double
51
+ public let opacity : Double
52
+
53
+ internal init ( red: Double , green: Double , blue: Double , opacity: Double ) {
54
+ self . red = red
55
+ self . green = green
56
+ self . blue = blue
57
+ self . opacity = opacity
58
+ }
59
+ }
60
+
61
+ extension Double {
62
+ fileprivate var hexString : String {
63
+ return String ( format: " %02X " , Int ( ( self * 255 ) . rounded ( ) ) )
64
+ }
65
+ }
66
+
67
+ public class _Resolved : AnyColorBox {
68
+ public let linearRed : Double
69
+ public let linearGreen : Double
70
+ public let linearBlue : Double
71
+ public let opacity : Double
72
+
73
+ internal init ( linearRed: Double , linearGreen: Double , linearBlue: Double , opacity: Double ) {
74
+ self . linearRed = linearRed
75
+ self . linearGreen = linearGreen
76
+ self . linearBlue = linearBlue
77
+ self . opacity = opacity
78
+ }
79
+
80
+ public var description : String {
81
+ return " # \( linearRed. hexString) \( linearGreen. hexString) \( linearBlue. hexString) \( opacity. hexString) "
82
+ }
83
+ }
84
+
1
85
public struct Color : View , Hashable , CustomStringConvertible {
2
86
public typealias Body = Never
3
87
4
- // These values should be private,
5
- // but then they are not accessible
6
- // in implementations of OpenSwiftUI
7
- public let _red : Double
8
- public let _green : Double
9
- public let _blue : Double
10
- public let _opacity : Double
88
+ public let provider : AnyColorBox
11
89
12
90
public enum RGBColorSpace : Equatable {
13
91
case sRGB
@@ -16,47 +94,60 @@ public struct Color: View, Hashable, CustomStringConvertible {
16
94
}
17
95
18
96
public init ( _ colorSpace: Color . RGBColorSpace = . sRGB, red: Double , green: Double , blue: Double , opacity: Double = 1 ) {
19
- self . _red = red
20
- self . _green = green
21
- self . _blue = blue
22
- self . _opacity = opacity
97
+ switch colorSpace {
98
+ case . sRGB:
99
+ self . provider = _Resolved ( linearRed: red, linearGreen: green, linearBlue: blue, opacity: opacity)
100
+ case . sRGBLinear:
101
+ self . provider = _Resolved ( linearRed: red, linearGreen: green, linearBlue: blue, opacity: opacity)
102
+ case . displayP3:
103
+ self . provider = DisplayP3 ( red: red, green: green, blue: blue, opacity: opacity)
104
+ }
23
105
}
24
106
25
107
public init ( _ colorSpace: Color . RGBColorSpace = . sRGB, white: Double , opacity: Double = 1 ) {
26
- self . _red = white
27
- self . _green = white
28
- self . _blue = white
29
- self . _opacity = opacity
108
+ switch colorSpace {
109
+ case . sRGB:
110
+ self . provider = _Resolved ( linearRed: white, linearGreen: white, linearBlue: white, opacity: opacity)
111
+ case . sRGBLinear:
112
+ self . provider = _Resolved ( linearRed: white, linearGreen: white, linearBlue: white, opacity: opacity)
113
+ case . displayP3:
114
+ self . provider = DisplayP3 ( red: white, green: white, blue: white, opacity: opacity)
115
+ }
30
116
}
31
117
32
118
public init ( hue: Double , saturation: Double , brightness: Double , opacity: Double = 1 ) {
33
- // TODO: Implement HSBA to RGBA conversion.
34
- fatalError ( " Not implemented " )
119
+ let rgb = Color . hsbToRGB ( hue: hue, saturation: saturation, brightness: brightness)
120
+ self . provider = _Resolved ( linearRed: rgb. red, linearGreen: rgb. green, linearBlue: rgb. blue, opacity: opacity)
121
+ }
122
+
123
+ internal init ( _ systemColor: SystemColorType . SystemColor ) {
124
+ self . provider = SystemColorType ( value: systemColor)
35
125
}
36
126
37
127
public var body : Never {
38
128
fatalError ( )
39
129
}
40
130
41
131
public var description : String {
42
- return " Red: \( _red ) , Green: \( _green ) , Blue: \( _blue ) "
132
+ return " \( provider ) "
43
133
}
44
134
}
45
135
46
136
extension Color {
47
- public static let clear : Color = Color ( hue: 0 , saturation: 0 , brightness: 0 , opacity: 0 )
48
- public static let black : Color = Color ( red: 0 , green: 0 , blue: 0 )
49
- public static let white : Color = Color ( red: 1 , green: 1 , blue: 1 )
50
- public static let gray : Color = Color ( red: 0.5 , green: 0.5 , blue: 0.5 )
51
- public static let red : Color = Color ( red: 1 , green: 0 , blue: 0 )
52
- public static let green : Color = Color ( red: 0 , green: 1 , blue: 0 )
53
- public static let blue : Color = Color ( red: 0 , green: 0 , blue: 1 )
54
- public static let orange : Color = Color ( red: 1 , green: 0.5 , blue: 0 )
55
- public static let yellow : Color = Color ( red: 1 , green: 1 , blue: 0 )
56
- public static let pink : Color = Color ( red: 1 , green: 0 , blue: 1 )
57
- public static let purple : Color = Color ( red: 0.5 , green: 0 , blue: 1 )
58
- public static let primary : Color = Color ( red: 1 , green: 1 , blue: 1 )
59
- public static let secondary : Color = Color ( red: 0.8 , green: 0.8 , blue: 0.8 )
137
+ public static let clear : Color = Color ( . clear)
138
+ public static let black : Color = Color ( . black)
139
+ public static let white : Color = Color ( . white)
140
+ public static let gray : Color = Color ( . gray)
141
+ public static let red : Color = Color ( . red)
142
+ public static let green : Color = Color ( . green)
143
+ public static let blue : Color = Color ( . blue)
144
+ public static let orange : Color = Color ( . orange)
145
+ public static let yellow : Color = Color ( . yellow)
146
+ public static let pink : Color = Color ( . pink)
147
+ public static let purple : Color = Color ( . purple)
148
+ public static let primary : Color = Color ( . primary)
149
+ public static let secondary : Color = Color ( . secondary)
150
+ public static let accentColor : Color = Color ( . accentColor)
60
151
}
61
152
62
153
extension View {
@@ -77,7 +168,53 @@ extension EnvironmentValues {
77
168
}
78
169
79
170
80
-
171
+ extension Color {
172
+ internal static func hsbToRGB( hue: Double , saturation: Double , brightness: Double ) -> ( red: Double , green: Double , blue: Double ) {
173
+ // Based on:
174
+ // http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
175
+
176
+ var red : Double = 0
177
+ var green : Double = 0
178
+ var blue : Double = 0
179
+
180
+ let i = floor ( hue * 6 )
181
+ let f = hue * 6 - i
182
+ let p = brightness * ( 1 - saturation)
183
+ let q = brightness * ( 1 - f * saturation)
184
+ let t = brightness * ( 1 - ( 1 - f) * saturation)
185
+
186
+ switch ( i. truncatingRemainder ( dividingBy: 6 ) ) {
187
+ case 0 :
188
+ red = brightness
189
+ green = t
190
+ blue = p
191
+ case 1 :
192
+ red = q
193
+ green = brightness
194
+ blue = p
195
+ case 2 :
196
+ red = p
197
+ green = brightness
198
+ blue = t
199
+ case 3 :
200
+ red = p
201
+ green = q
202
+ blue = brightness
203
+ case 4 :
204
+ red = t
205
+ green = p
206
+ blue = brightness
207
+ case 5 :
208
+ red = brightness
209
+ green = p
210
+ blue = q
211
+ default :
212
+ break
213
+ }
214
+
215
+ return ( red, green, blue)
216
+ }
217
+ }
81
218
82
219
public enum ColorScheme : CaseIterable {
83
220
case light
0 commit comments