@@ -60,6 +60,7 @@ extension Color.Representation: Hashable {
6060 }
6161}
6262
63+ /// An object that stores color data and sometimes opacity.
6364public struct Color {
6465 private let value : Representation
6566
@@ -90,6 +91,134 @@ public struct Color {
9091 public init ( dynamicProvider block: @escaping ( TraitCollection ) -> Color ) {
9192 self . value = . func( block)
9293 }
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+ }
93222}
94223
95224extension COLORREF {
@@ -115,8 +244,8 @@ extension Color {
115244 return WinSDK . COLORREF ( red: f ( 5.0 ) , green: f ( 3.0 ) , blue: f ( 1.0 ) )
116245 case . gray( let w, _) :
117246 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
120249 }
121250 }
122251}
@@ -150,14 +279,14 @@ extension Color {
150279}
151280
152281extension 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 ) {
155283 self . init ( red: Double ( red) / 255.0 , green: Double ( green) / 255.0 ,
156284 blue: Double ( blue) / 255.0 , alpha: Double ( alpha) )
157285 }
158286}
159287
160288// MARK - Standard Colors
289+
161290extension Color {
162291 // MARK - Adaptable Colors
163292
0 commit comments