1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2012 Benjamin Otte <otte@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include "gtkhslaprivate.h"
21
22 #include <math.h>
23
24 void
_gtk_hsla_init(GtkHSLA * hsla,double hue,double saturation,double lightness,double alpha)25 _gtk_hsla_init (GtkHSLA *hsla,
26 double hue,
27 double saturation,
28 double lightness,
29 double alpha)
30 {
31 g_return_if_fail (hsla != NULL);
32
33 if (hue >= 0)
34 hsla->hue = fmod (hue, 360);
35 else
36 hsla->hue = fmod (hue, 360) + 360;
37 hsla->saturation = CLAMP (saturation, 0, 1);
38 hsla->lightness = CLAMP (lightness, 0, 1);
39 hsla->alpha = CLAMP (alpha, 0, 1);
40 }
41
42 void
_gtk_hsla_init_from_rgba(GtkHSLA * hsla,const GdkRGBA * rgba)43 _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
44 const GdkRGBA *rgba)
45 {
46 gdouble min;
47 gdouble max;
48 gdouble red;
49 gdouble green;
50 gdouble blue;
51 gdouble delta;
52
53 g_return_if_fail (hsla != NULL);
54 g_return_if_fail (rgba != NULL);
55
56 red = rgba->red;
57 green = rgba->green;
58 blue = rgba->blue;
59
60 if (red > green)
61 {
62 if (red > blue)
63 max = red;
64 else
65 max = blue;
66
67 if (green < blue)
68 min = green;
69 else
70 min = blue;
71 }
72 else
73 {
74 if (green > blue)
75 max = green;
76 else
77 max = blue;
78
79 if (red < blue)
80 min = red;
81 else
82 min = blue;
83 }
84
85 hsla->lightness = (max + min) / 2;
86 hsla->saturation = 0;
87 hsla->hue = 0;
88 hsla->alpha = rgba->alpha;
89
90 if (max != min)
91 {
92 if (hsla->lightness <= 0.5)
93 hsla->saturation = (max - min) / (max + min);
94 else
95 hsla->saturation = (max - min) / (2 - max - min);
96
97 delta = max -min;
98 if (red == max)
99 hsla->hue = (green - blue) / delta;
100 else if (green == max)
101 hsla->hue = 2 + (blue - red) / delta;
102 else if (blue == max)
103 hsla->hue = 4 + (red - green) / delta;
104
105 hsla->hue *= 60;
106 if (hsla->hue < 0.0)
107 hsla->hue += 360;
108 }
109 }
110
111 void
_gdk_rgba_init_from_hsla(GdkRGBA * rgba,const GtkHSLA * hsla)112 _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
113 const GtkHSLA *hsla)
114 {
115 gdouble hue;
116 gdouble lightness;
117 gdouble saturation;
118 gdouble m1, m2;
119
120 lightness = hsla->lightness;
121 saturation = hsla->saturation;
122
123 if (lightness <= 0.5)
124 m2 = lightness * (1 + saturation);
125 else
126 m2 = lightness + saturation - lightness * saturation;
127 m1 = 2 * lightness - m2;
128
129 rgba->alpha = hsla->alpha;
130
131 if (saturation == 0)
132 {
133 rgba->red = lightness;
134 rgba->green = lightness;
135 rgba->blue = lightness;
136 }
137 else
138 {
139 hue = hsla->hue + 120;
140 while (hue > 360)
141 hue -= 360;
142 while (hue < 0)
143 hue += 360;
144
145 if (hue < 60)
146 rgba->red = m1 + (m2 - m1) * hue / 60;
147 else if (hue < 180)
148 rgba->red = m2;
149 else if (hue < 240)
150 rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
151 else
152 rgba->red = m1;
153
154 hue = hsla->hue;
155 while (hue > 360)
156 hue -= 360;
157 while (hue < 0)
158 hue += 360;
159
160 if (hue < 60)
161 rgba->green = m1 + (m2 - m1) * hue / 60;
162 else if (hue < 180)
163 rgba->green = m2;
164 else if (hue < 240)
165 rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
166 else
167 rgba->green = m1;
168
169 hue = hsla->hue - 120;
170 while (hue > 360)
171 hue -= 360;
172 while (hue < 0)
173 hue += 360;
174
175 if (hue < 60)
176 rgba->blue = m1 + (m2 - m1) * hue / 60;
177 else if (hue < 180)
178 rgba->blue = m2;
179 else if (hue < 240)
180 rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
181 else
182 rgba->blue = m1;
183 }
184 }
185
186 void
_gtk_hsla_shade(GtkHSLA * dest,const GtkHSLA * src,double factor)187 _gtk_hsla_shade (GtkHSLA *dest,
188 const GtkHSLA *src,
189 double factor)
190 {
191 g_return_if_fail (dest != NULL);
192 g_return_if_fail (src != NULL);
193
194 dest->hue = src->hue;
195
196 dest->lightness = src->lightness * factor;
197 dest->lightness = CLAMP (dest->lightness, 0.0, 1.0);
198
199 dest->saturation = src->saturation * factor;
200 dest->saturation = CLAMP (dest->saturation, 0.0, 1.0);
201
202 dest->alpha = src->alpha;
203 }
204