@@ -60,6 +60,7 @@ extension Color.Representation: Hashable {
60
60
}
61
61
}
62
62
63
+ /// An object that stores color data and sometimes opacity.
63
64
public struct Color {
64
65
private let value : Representation
65
66
@@ -90,6 +91,134 @@ public struct Color {
90
91
public init ( dynamicProvider block: @escaping ( TraitCollection ) -> Color ) {
91
92
self . value = . func( block)
92
93
}
94
+
95
+ // MARK - Getting the Color Information
96
+
97
+ /// Returns the components that form the color in the HSB color space.
98
+ ///
99
+ /// If the color is in a compatible color space, it converts into the HSB
100
+ /// color space, and its components return to your application. If the color
101
+ /// isn’t in a compatible color space, the parameters don’t change.
102
+ public func getHue( _ hue: UnsafeMutablePointer < Double > ? ,
103
+ saturation: UnsafeMutablePointer < Double > ? ,
104
+ brightness: UnsafeMutablePointer < Double > ? ,
105
+ alpha: UnsafeMutablePointer < Double > ? ) -> Bool {
106
+ switch self . value {
107
+ case . gray:
108
+ fatalError ( " cannot convert Gray to HSBA " )
109
+ case . rgba( let r, let g, let b, let a) :
110
+ func rgb2hsb( _ r: Double , _ g: Double , _ b: Double )
111
+ -> ( Double , Double , Double ) {
112
+ let V = max ( r, g, b)
113
+ let m = min ( r, g, b)
114
+ let delta = V - m
115
+
116
+ var hue : Double
117
+ if V == 0.0 { hue = 0.0 }
118
+ else if V == r { hue = ( g - b) / delta }
119
+ else if V == g { hue = 2.0 + ( b - r) / delta }
120
+ else if V == b { hue = 4.0 + ( r - g) / delta }
121
+ else { fatalError ( " maximum must be one of the values " ) }
122
+
123
+ hue = ucrt. fmodl ( hue + 6.0 , 6.0 )
124
+ return ( hue == 0.0 ? 1.0 : hue / 6.0 , V, V == 0.0 ? 0.0 : delta / V)
125
+ }
126
+
127
+ let ( h, s, b) = rgb2hsb ( r, g, b)
128
+
129
+ hue? . pointee = h
130
+ brightness? . pointee = s
131
+ saturation? . pointee = b
132
+ alpha? . pointee = a
133
+ return true
134
+ case . hsba( let h, let s, let b, let a) :
135
+ hue? . pointee = h
136
+ saturation? . pointee = s
137
+ brightness? . pointee = b
138
+ alpha? . pointee = a
139
+ return true
140
+ case . func:
141
+ return resolvedColor ( with: TraitCollection . current)
142
+ . getHue ( hue, saturation: saturation, brightness: brightness,
143
+ alpha: alpha)
144
+ }
145
+ }
146
+
147
+ /// Returns the components that form the color in the RGB color space.
148
+ ///
149
+ /// If the color is in a compatible color space, it converts into RGB format
150
+ /// and its components return to your application. If the color isn’t in a
151
+ /// compatible color space, the parameters don’t change.
152
+ public func getRed( _ red: UnsafeMutablePointer < Double > ? ,
153
+ green: UnsafeMutablePointer < Double > ? ,
154
+ blue: UnsafeMutablePointer < Double > ? ,
155
+ alpha: UnsafeMutablePointer < Double > ? ) -> Bool {
156
+ switch self . value {
157
+ case . gray:
158
+ fatalError ( " cannot convert Gray to RGBA " )
159
+ case . rgba( let r, let g, let b, let a) :
160
+ red? . pointee = r
161
+ green? . pointee = g
162
+ blue? . pointee = b
163
+ alpha? . pointee = a
164
+ return true
165
+ case . hsba( let h, let s, let b, let a) :
166
+ func f( _ n: Double ) -> Double {
167
+ let k = ucrt. fmod ( n + ( 6.0 * h) , 6.0 )
168
+ return b - b * s * max( 0 , min ( k, 4 - k, 1 ) )
169
+ }
170
+ red? . pointee = f ( 5.0 )
171
+ green? . pointee = f ( 3.0 )
172
+ blue? . pointee = f ( 1.0 )
173
+ alpha? . pointee = a
174
+ return true
175
+ case . func:
176
+ return resolvedColor ( with: TraitCollection . current)
177
+ . getRed ( red, green: green, blue: blue, alpha: alpha)
178
+ }
179
+ }
180
+
181
+ /// Returns the grayscale components of the color.
182
+ ///
183
+ /// If the color is in a compatible color space, it converts into grayscale
184
+ /// format and its returned to your application. If the color isn’t in a
185
+ /// compatible color space, the parameters don’t change.
186
+ public func getWhite( _ white: UnsafeMutablePointer < Double > ? ,
187
+ alpha: UnsafeMutablePointer < Double > ? ) -> Bool {
188
+ switch self . value {
189
+ case . gray( let w, let a) :
190
+ white? . pointee = w
191
+ alpha? . pointee = a
192
+ return true
193
+ case . rgba( let r, let g, let b, let a) :
194
+ // The weighted or luminosity method uses the weighted average of the
195
+ // channels based on the wavelength of the channel.
196
+ // The constants here are from ITU-R BT.601-7.
197
+ white? . pointee = r * 0.299 + g * 0.587 + b * 0.114
198
+ alpha? . pointee = a
199
+ return true
200
+ case . hsba( let h, let s, let b, let a) :
201
+ func f( _ n: Double ) -> Double {
202
+ let k = ucrt. fmod ( n + ( 6.0 * h) , 6.0 )
203
+ return b - b * s * max( 0 , min ( k, 4 - k, 1 ) )
204
+ }
205
+ white? . pointee = f ( 5.0 ) * 0.299 + f( 3.0 ) * 0.587 + f( 1.0 ) * 0.114
206
+ alpha? . pointee = a
207
+ return true
208
+ case . func:
209
+ return resolvedColor ( with: TraitCollection . current)
210
+ . getWhite ( white, alpha: alpha)
211
+ }
212
+ }
213
+
214
+ // MARK - Resolving a Dynamically Generated Color
215
+
216
+ /// Returns the version of the current color that results from the specified
217
+ /// traits.
218
+ public func resolvedColor( with traitCollection: TraitCollection ) -> Color {
219
+ guard case let . func( body) = self . value else { return self }
220
+ return body ( traitCollection)
221
+ }
93
222
}
94
223
95
224
extension COLORREF {
@@ -115,8 +244,8 @@ extension Color {
115
244
return WinSDK . COLORREF ( red: f ( 5.0 ) , green: f ( 3.0 ) , blue: f ( 1.0 ) )
116
245
case . gray( let w, _) :
117
246
return WinSDK . COLORREF ( red: w * 255.0 , green: w * 255.0 , blue: w * 255.0 )
118
- case . func( let body ) :
119
- return body ( TraitCollection . current) . COLORREF
247
+ case . func:
248
+ return self . resolvedColor ( with : TraitCollection . current) . COLORREF
120
249
}
121
250
}
122
251
}
@@ -150,14 +279,14 @@ extension Color {
150
279
}
151
280
152
281
extension Color {
153
- internal init ( red: Int , green: Int , blue: Int ,
154
- alpha: Double = 1.0 ) {
282
+ internal init ( red: Int , green: Int , blue: Int , alpha: Double = 1.0 ) {
155
283
self . init ( red: Double ( red) / 255.0 , green: Double ( green) / 255.0 ,
156
284
blue: Double ( blue) / 255.0 , alpha: Double ( alpha) )
157
285
}
158
286
}
159
287
160
288
// MARK - Standard Colors
289
+
161
290
extension Color {
162
291
// MARK - Adaptable Colors
163
292
0 commit comments