]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkhsla.c
symboliccolor: Split out HSLA code
[~andy/gtk] / gtk / gtkhsla.c
diff --git a/gtk/gtkhsla.c b/gtk/gtkhsla.c
new file mode 100644 (file)
index 0000000..a788497
--- /dev/null
@@ -0,0 +1,185 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2012 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkhslaprivate.h"
+
+#include <math.h>
+
+void
+_gtk_hsla_init (GtkHSLA *hsla,
+                double   hue,
+                double   saturation,
+                double   lightness,
+                double   alpha)
+{
+  g_return_if_fail (hsla != NULL);
+
+  if (hue >= 0)
+    hsla->hue = fmod (hue, 360);
+  else
+    hsla->hue = fmod (hue, 360) + 360;
+  hsla->saturation = CLAMP (saturation, 0, 1);
+  hsla->lightness = CLAMP (lightness, 0, 1);
+  hsla->alpha = CLAMP (alpha, 0, 1);
+}
+
+void
+_gtk_hsla_init_from_rgba (GtkHSLA       *hsla,
+                          const GdkRGBA *rgba)
+{
+  gdouble min;
+  gdouble max;
+  gdouble red;
+  gdouble green;
+  gdouble blue;
+  gdouble delta;
+  
+  g_return_if_fail (hsla != NULL);
+  g_return_if_fail (rgba != NULL);
+
+  red = rgba->red;
+  green = rgba->green;
+  blue = rgba->blue;
+  
+  if (red > green)
+    {
+      if (red > blue)
+        max = red;
+      else
+        max = blue;
+      
+      if (green < blue)
+        min = green;
+      else
+        min = blue;
+    }
+  else
+    {
+      if (green > blue)
+        max = green;
+      else
+        max = blue;
+      
+      if (red < blue)
+        min = red;
+      else
+        min = blue;
+    }
+  
+  hsla->lightness = (max + min) / 2;
+  hsla->saturation = 0;
+  hsla->hue = 0;
+  hsla->alpha = rgba->alpha;
+  
+  if (max != min)
+    {
+      if (hsla->lightness <= 0.5)
+        hsla->saturation = (max - min) / (max + min);
+      else
+        hsla->saturation = (max - min) / (2 - max - min);
+      
+      delta = max -min;
+      if (red == max)
+        hsla->hue = (green - blue) / delta;
+      else if (green == max)
+        hsla->hue = 2 + (blue - red) / delta;
+      else if (blue == max)
+        hsla->hue = 4 + (red - green) / delta;
+      
+      hsla->hue *= 60;
+      if (hsla->hue < 0.0)
+        hsla->hue += 360;
+    }
+}
+
+void
+_gdk_rgba_init_from_hsla (GdkRGBA       *rgba,
+                          const GtkHSLA *hsla)
+{
+  gdouble hue;
+  gdouble lightness;
+  gdouble saturation;
+  gdouble m1, m2;
+  
+  lightness = hsla->lightness;
+  saturation = hsla->saturation;
+  
+  if (lightness <= 0.5)
+    m2 = lightness * (1 + saturation);
+  else
+    m2 = lightness + saturation - lightness * saturation;
+  m1 = 2 * lightness - m2;
+  
+  rgba->alpha = hsla->alpha;
+
+  if (saturation == 0)
+    {
+      rgba->red = lightness;
+      rgba->green = lightness;
+      rgba->blue = lightness;
+    }
+  else
+    {
+      hue = hsla->hue + 120;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+      
+      if (hue < 60)
+        rgba->red = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        rgba->red = m2;
+      else if (hue < 240)
+        rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        rgba->red = m1;
+      
+      hue = hsla->hue;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+      
+      if (hue < 60)
+        rgba->green = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        rgba->green = m2;
+      else if (hue < 240)
+        rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        rgba->green = m1;
+      
+      hue = hsla->hue - 120;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+      
+      if (hue < 60)
+        rgba->blue = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        rgba->blue = m2;
+      else if (hue < 240)
+        rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        rgba->blue = m1;
+    }
+}
+