@@ -2,18 +2,18 @@ module Color where
22
33{-| Library for working with colors. Includes
44[RGB](https://en.wikipedia.org/wiki/RGB_color_model) and
5−[HSV](http://en.wikipedia.org/wiki/HSL_and_HSV) creation, gradients, and
5+[HSL](http://en.wikipedia.org/wiki/HSL_and_HSV) creation, gradients, and
66built-in names.
77
88# Creation
9−@docs rgb, rgba, hsv, hsva, greyscale, grayscale
10−
11−# From Other Colors
12−@docs complement
9+@docs rgb, rgba, hsl, hsla, greyscale, grayscale, complement
1310
1411# Gradients
1512@docs linear, radial
1613
14+# Extracting Colors
15+@docs toRgb, toHsl
16+
1717# Built-in Colors
1818These colors come from the [Tango
1919palette](http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines)
@@ -24,12 +24,10 @@ comes with a light and dark version.
2424@docs red, orange, yellow, green, blue, purple, brown
2525
2626### Light
27−@docs lightRed, lightOrange, lightYellow, lightGreen, lightBlue, lightPurple,
28− lightBrown
27+@docs lightRed, lightOrange, lightYellow, lightGreen, lightBlue, lightPurple, lightBrown
2928
3029### Dark
31−@docs darkRed, darkOrange, darkYellow, darkGreen, darkBlue, darkPurple,
32− darkBrown
30+@docs darkRed, darkOrange, darkYellow, darkGreen, darkBlue, darkPurple, darkBrown
3331
3432### Eight Shades of Grey
3533These colors are a compatible series of shades of grey, fitting nicely
@@ -42,133 +40,223 @@ that has never helped me remember which one I should be writing.
4240
4341-}
4442
45−import Native.Color
46−import Basics ((-))
43+import Basics (..)
4744
48−data Color = Color Int Int Int Float
45+data Color
46+ = RGBA Int Int Int Float
47+ | HSLA Float Float Float Float
4948
5049{-| Create RGB colors with an alpha component for transparency.
5150The alpha component is specified with numbers between 0 and 1. -}
5251rgba : Int -> Int -> Int -> Float -> Color
53−rgba = Color
52+rgba = RGBA
5453
5554{-| Create RGB colors from numbers between 0 and 255 inclusive. -}
5655rgb : Int -> Int -> Int -> Color
57−rgb r g b = Color r g b 1
56+rgb r g b = RGBA r g b 1
57+
58+{-| Produce a gray based on the input. 0 is white, 1 is black. -}
59+grayscale : Float -> Color
60+grayscale p = HSLA 0 0 (1-p) 1
61+
62+greyscale : Float -> Color
63+greyscale p = HSLA 0 0 (1-p) 1
64+
65+{-| Produce a “complementary color”. The two colors will
66+accent each other. This is the same as rotating the hue by 180°.
67+-}
68+complement : Color -> Color
69+complement color =
70+ case color of
71+ HSLA h s l a -> hsla (h + degrees 180) s l a
72+ RGBA r g b a -> let (h,s,l) = rgbToHsl r g b
73+ in hsla (h + degrees 180) s l a
74+
75+{-| Create [HSL colors](http://en.wikipedia.org/wiki/HSL_and_HSV)
76+with an alpha component for transparency.
77+-}
78+hsla : Float -> Float -> Float -> Float -> Color
79+hsla hue saturation lightness alpha =
80+ HSLA (hue - toFloat (floor (hue / (2*pi)))) saturation lightness alpha
81+
82+{-| Create [HSL colors](http://en.wikipedia.org/wiki/HSL_and_HSV). This is very
83+convenient for creating colors that cycle and shift. Hue is an angle and should
84+be given in standard Elm angles (radians).
85+-}
86+hsl : Float -> Float -> Float -> Color
87+hsl hue saturation lightness =
88+ hsla hue saturation lightness 1
89+
90+{-| Extract the the components of a color in the HSL format.
91+-}
92+toHsl : Color -> { hue:Float, saturation:Float, lightness:Float, alpha:Float }
93+toHsl color =
94+ case color of
95+ HSLA h s l a -> { hue=h, saturation=s, lightness=l, alpha=a }
96+ RGBA r g b a ->
97+ let (h,s,l) = rgbToHsl r g b
98+ in { hue=h, saturation=s, lightness=l, alpha=a }
99+
100+{-| Extract the the components of a color in the RGB format.
101+-}
102+toRgb : Color -> { red:Int, green:Int, blue:Int, alpha:Float }
103+toRgb color =
104+ case color of
105+ RGBA r g b a -> { red=r, green=g, blue=b, alpha=a }
106+ HSLA h s l a ->
107+ let (r,g,b) = hslToRgb h s l
108+ in { red = round (255 * r)
109+ , green = round (255 * g)
110+ , blue = round (255 * b)
111+ , alpha = a
112+ }
113+
114+fmod : Float -> Int -> Float
115+fmod f n =
116+ let integer = floor f
117+ in toFloat (integer `mod` n) + f - toFloat integer
118+
119+rgbToHsl : Int -> Int -> Int -> (Float,Float,Float)
120+rgbToHsl red green blue =
121+ let r = toFloat red / 255
122+ g = toFloat green / 255
123+ b = toFloat blue / 255
124+
125+ cMax = max (max r g) b
126+ cMin = min (min r g) b
127+
128+ c = cMax - cMin
129+
130+ hue = degrees 60 * if | cMax == r -> ((g - b) / c) `fmod` 6
131+ | cMax == g -> ((b - r) / c) + 2
132+ | cMax == b -> ((r - g) / c) + 4
133+
134+ lightness = (cMax + cMin) / 2
135+
136+ saturation =
137+ if lightness == 0
138+ then 0
139+ else c / (1 - abs (2 * lightness - 1))
140+ in
141+ (hue, saturation, lightness)
142+
143+hslToRgb : Float -> Float -> Float -> (Float,Float,Float)
144+hslToRgb hue saturation lightness =
145+ let chroma = (1 - abs (2 * lightness - 1)) * saturation
146+ hue' = hue / degrees 60
147+
148+ x = chroma * (1 - abs (fmod hue' 2 - 1))
149+
150+ (r,g,b) = if | hue' < 0 -> (0, 0, 0)
151+ | hue' < 1 -> (chroma, x, 0)
152+ | hue' < 2 -> (x, chroma, 0)
153+ | hue' < 3 -> (0, chroma, x)
154+ | hue' < 4 -> (0, x, chroma)
155+ | hue' < 5 -> (x, 0, chroma)
156+ | hue' < 6 -> (chroma, 0, x)
157+ | otherwise -> (0, 0, 0)
158+
159+ m = lightness - chroma / 2
160+ in
161+ (r + m, g + m, b + m)
162+
163+--toV3 : Color -> V3
164+
165+--toV4 : Color -> V4
166+
167+data Gradient
168+ = Linear (Float,Float) (Float,Float) [(Float,Color)]
169+ | Radial (Float,Float) Float (Float,Float) Float [(Float,Color)]
170+
171+{-| Create a linear gradient. Takes a start and end point and then a series of
172+“color stops” that indicate how to interpolate between the start and
173+end points. See [this example](/edit/examples/Elements/LinearGradient.elm) for a
174+more visual explanation. -}
175+linear : (number, number) -> (number, number) -> [(Float,Color)] -> Gradient
176+linear = Linear
177+
178+{-| Create a radial gradient. First takes a start point and inner radius. Then
179+takes an end point and outer radius. It then takes a series of “color
180+stops” that indicate how to interpolate between the inner and outer
181+circles. See [this example](/edit/examples/Elements/RadialGradient.elm) for a
182+more visual explanation. -}
183+radial : (number,number) -> number -> (number,number) -> number -> [(Float,Color)] -> Gradient
184+radial = Radial
185+
186+
187+-- BUILT-IN COLORS
58188
59189lightRed : Color
60−lightRed = Color 239 41 41 1
190+lightRed = RGBA 239 41 41 1
61191red : Color
62−red = Color 204 0 0 1
192+red = RGBA 204 0 0 1
63193darkRed : Color
64−darkRed = Color 164 0 0 1
194+darkRed = RGBA 164 0 0 1
65195
66196lightOrange : Color
67−lightOrange = Color 252 175 62 1
197+lightOrange = RGBA 252 175 62 1
68198orange : Color
69−orange = Color 245 121 0 1
199+orange = RGBA 245 121 0 1
70200darkOrange : Color
71−darkOrange = Color 206 92 0 1
201+darkOrange = RGBA 206 92 0 1
72202
73203lightYellow : Color
74−lightYellow = Color 255 233 79 1
204+lightYellow = RGBA 255 233 79 1
75205yellow : Color
76−yellow = Color 237 212 0 1
206+yellow = RGBA 237 212 0 1
77207darkYellow : Color
78−darkYellow = Color 196 160 0 1
208+darkYellow = RGBA 196 160 0 1
79209
80210lightGreen : Color
81−lightGreen = Color 138 226 52 1
211+lightGreen = RGBA 138 226 52 1
82212green : Color
83−green = Color 115 210 22 1
213+green = RGBA 115 210 22 1
84214darkGreen : Color
85−darkGreen = Color 78 154 6 1
215+darkGreen = RGBA 78 154 6 1
86216
87217lightBlue : Color
88−lightBlue = Color 114 159 207 1
218+lightBlue = RGBA 114 159 207 1
89219blue : Color
90−blue = Color 52 101 164 1
220+blue = RGBA 52 101 164 1
91221darkBlue : Color
92−darkBlue = Color 32 74 135 1
222+darkBlue = RGBA 32 74 135 1
93223
94224lightPurple : Color
95−lightPurple = Color 173 127 168 1
225+lightPurple = RGBA 173 127 168 1
96226purple : Color
97−purple = Color 117 80 123 1
227+purple = RGBA 117 80 123 1
98228darkPurple : Color
99−darkPurple = Color 92 53 102 1
229+darkPurple = RGBA 92 53 102 1
100230
101231lightBrown : Color
102−lightBrown = Color 233 185 110 1
232+lightBrown = RGBA 233 185 110 1
103233brown : Color
104−brown = Color 193 125 17 1
234+brown = RGBA 193 125 17 1
105235darkBrown : Color
106−darkBrown = Color 143 89 2 1
236+darkBrown = RGBA 143 89 2 1
107237
108238black : Color
109−black = Color 0 0 0 1
239+black = RGBA 0 0 0 1
110240white : Color
111−white = Color 255 255 255 1
241+white = RGBA 255 255 255 1
112242
113243lightGrey : Color
114−lightGrey = Color 238 238 236 1
244+lightGrey = RGBA 238 238 236 1
115245grey : Color
116−grey = Color 211 215 207 1
246+grey = RGBA 211 215 207 1
117247darkGrey : Color
118−darkGrey = Color 186 189 182 1
248+darkGrey = RGBA 186 189 182 1
119249
120250lightGray : Color
121−lightGray = Color 238 238 236 1
251+lightGray = RGBA 238 238 236 1
122252gray : Color
123−gray = Color 211 215 207 1
253+gray = RGBA 211 215 207 1
124254darkGray : Color
125−darkGray = Color 186 189 182 1
255+darkGray = RGBA 186 189 182 1
126256
127257lightCharcoal : Color
128−lightCharcoal = Color 136 138 133 1
258+lightCharcoal = RGBA 136 138 133 1
129259charcoal : Color
130−charcoal = Color 85 87 83 1
260+charcoal = RGBA 85 87 83 1
131261darkCharcoal : Color
132−darkCharcoal = Color 46 52 54 1
133−
134−{-| Produce a gray based on the input. 0 is white, 1 is black. -}
135−grayscale : Float -> Color
136−grayscale p = hsv 0 0 (1-p)
137−
138−greyscale : Float -> Color
139−greyscale p = hsv 0 0 (1-p)
140−
141−{-| Produce a “complementary color”.
142−The two colors will accent each other. -}
143−complement : Color -> Color
144−complement = Native.Color.complement
145−
146−{-| Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV)
147−with an alpha component for transparency. -}
148−hsva : Float -> Float -> Float -> Float -> Color
149−hsva = Native.Color.hsva
150−
151−{-| Create [HSV colors](http://en.wikipedia.org/wiki/HSL_and_HSV). This is very
152−convenient for creating colors that cycle and shift. Hue is an angle and should
153−be given in standard Elm angles (radians). -}
154−hsv : Float -> Float -> Float -> Color
155−hsv = Native.Color.hsv
156−
157−data Gradient
158− = Linear (Float,Float) (Float,Float) [(Float,Color)]
159− | Radial (Float,Float) Float (Float,Float) Float [(Float,Color)]
160−
161−{-| Create a linear gradient. Takes a start and end point and then a series of
162−“color stops” that indicate how to interpolate between the start and
163−end points. See [this example](/edit/examples/Elements/LinearGradient.elm) for a
164−more visual explanation. -}
165−linear : (number, number) -> (number, number) -> [(Float,Color)] -> Gradient
166−linear = Linear
167−
168−{-| Create a radial gradient. First takes a start point and inner radius. Then
169−takes an end point and outer radius. It then takes a series of “color
170−stops” that indicate how to interpolate between the inner and outer
171−circles. See [this example](/edit/examples/Elements/RadialGradient.elm) for a
172−more visual explanation. -}
173−radial : (number,number) -> number -> (number,number) -> number -> [(Float,Color)] -> Gradient
174−radial = Radial
262+darkCharcoal = RGBA 46 52 54 1