diff options
Diffstat (limited to 'ccss-gtk')
-rw-r--r-- | ccss-gtk/Makefile.am | 4 | ||||
-rw-r--r-- | ccss-gtk/ccss-gtk-color.c | 255 | ||||
-rw-r--r-- | ccss-gtk/ccss-gtk-color.h | 53 | ||||
-rw-r--r-- | ccss-gtk/ccss-gtk-functions.c | 385 | ||||
-rw-r--r-- | ccss-gtk/ccss-gtk-functions.h | 40 | ||||
-rw-r--r-- | ccss-gtk/ccss-gtk-grammar.c | 2 |
6 files changed, 739 insertions, 0 deletions
diff --git a/ccss-gtk/Makefile.am b/ccss-gtk/Makefile.am index fc83a7a..118a339 100644 --- a/ccss-gtk/Makefile.am +++ b/ccss-gtk/Makefile.am @@ -29,6 +29,10 @@ libccss_gtk_1_la_LIBADD = \ libccss_gtk_1_la_SOURCES = \ $(headers_DATA) \ + ccss-gtk-color.c \ + ccss-gtk-color.h \ + ccss-gtk-functions.c \ + ccss-gtk-functions.h \ ccss-gtk-grammar.c \ ccss-gtk-property.c \ ccss-gtk-property.h \ diff --git a/ccss-gtk/ccss-gtk-color.c b/ccss-gtk/ccss-gtk-color.c new file mode 100644 index 0000000..6e7e3ce --- /dev/null +++ b/ccss-gtk/ccss-gtk-color.c @@ -0,0 +1,255 @@ +/* vim: set ts=8 sw=8 noexpandtab: */ + +/* The Cairo CSS Drawing Library. + * Copyright (C) 2008 Robert Staudinger + * + * Portions of this file are derived from gtkrc.c, licensed under + * the GNU Lesser General Public License; either version 2 of the + * License, or (at your option) any later version. Copyright (C) + * the GTK+ Team, see the ChangeLog at ftp://ftp.gtk.org/pub/gtk/. + * + * 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, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <gtk/gtk.h> +#include "ccss-gtk-color.h" +#include "config.h" + +bool +ccss_gtk_color_lookup (char const *spec, + GdkColor *color) +{ + GtkSettings *settings; + GHashTable *colors; + GdkColor *system_color; + + g_return_val_if_fail (spec, FALSE); + + settings = gtk_settings_get_default (); + colors = NULL; + g_object_get (G_OBJECT (settings), "color-hash", &colors, NULL); + g_return_val_if_fail (colors, FALSE); + + system_color = (GdkColor *) g_hash_table_lookup (colors, spec); + if (system_color) { + color->red = system_color->red; + color->green = system_color->green; + color->blue = system_color->blue; + return TRUE; + } + + /* Try to parse the color. */ + return gdk_color_parse (spec, color); +} + +static void +rgb_to_hls (gdouble *r, + gdouble *g, + gdouble *b) +{ + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + 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; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void +hls_to_rgb (gdouble *h, + gdouble *l, + gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1 + (m2 - m1) * (240 - hue) / 60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1 + (m2 - m1) * (240 - hue) / 60; + else + g = m1; + + hue = *h - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1 + (m2 - m1) * (240 - hue) / 60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} + +bool +ccss_gtk_color_mix (double factor, + GdkColor const *color1, + GdkColor const *color2, + GdkColor *result) +{ + result->red = factor * color1->red + (1.0 - factor) * color2->red; + result->green = factor * color1->green + (1.0 - factor) * color2->green; + result->blue = factor * color1->blue + (1.0 - factor) * color2->blue; + + return TRUE; +} + +bool +ccss_gtk_color_shade (double factor, + GdkColor *color) +{ + gdouble red; + gdouble green; + gdouble blue; + + red = (gdouble) color->red / 65535.0; + green = (gdouble) color->green / 65535.0; + blue = (gdouble) color->blue / 65535.0; + + rgb_to_hls (&red, &green, &blue); + + green *= factor; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= factor; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + hls_to_rgb (&red, &green, &blue); + + color->red = (guint16) (red * 65535.0); + color->green = (guint16) (green * 65535.0); + color->blue = (guint16) (blue * 65535.0); + + return TRUE; +} + diff --git a/ccss-gtk/ccss-gtk-color.h b/ccss-gtk/ccss-gtk-color.h new file mode 100644 index 0000000..01e66cd --- /dev/null +++ b/ccss-gtk/ccss-gtk-color.h @@ -0,0 +1,53 @@ +/* vim: set ts=8 sw=8 noexpandtab: */ + +/* The Gtk+ CSS Drawing Library. + * Copyright (C) 2008 Robert Staudinger + * + * 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, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CCSS_GTK_COLOR_H +#define CCSS_GTK_COLOR_H + +#ifndef CCSS_GTK_H + #ifndef CCSS_GTK_BUILD + #error "Only <ccss-gtk/ccss-gtk.h> can be included directly." + #endif +#endif + +#include <ccss/ccss.h> +#include <gdk/gdk.h> + +CCSS_BEGIN_DECLS + +bool +ccss_gtk_color_lookup (char const *spec, + GdkColor *color); + +bool +ccss_gtk_color_mix (double factor, + GdkColor const *color1, + GdkColor const *color2, + GdkColor *result); + +bool +ccss_gtk_color_shade (double factor, + GdkColor *color); + +CCSS_END_DECLS + +#endif /* CCSS_GTK_COLOR_H */ + diff --git a/ccss-gtk/ccss-gtk-functions.c b/ccss-gtk/ccss-gtk-functions.c new file mode 100644 index 0000000..138ebf7 --- /dev/null +++ b/ccss-gtk/ccss-gtk-functions.c @@ -0,0 +1,385 @@ +/* vim: set ts=8 sw=8 noexpandtab: */ + +/* The Gtk+ CSS Drawing Library. + * Copyright (C) 2008 Robert Staudinger + * + * 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, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <ccss/ccss.h> +#include <gtk/gtk.h> +#include "ccss-gtk-functions.h" +#include "ccss-gtk-color.h" +#include "config.h" + +#ifdef CCSS_WITH_SOUP +#include <libsoup/soup.h> +#endif + +/* + * FIXME: make this bullet proof wrt uri scheme. + */ +static char * +url (GSList const *args, + void *user_data) +{ + char *resolved_path; + char *ret; +#ifdef CCSS_WITH_SOUP + char *given_path; + SoupURI *uri; + + g_return_val_if_fail (args, NULL); + + given_path = g_strdup_printf ("file:///%s", (char const *) args->data); + uri = soup_uri_new (given_path); + g_free (given_path), given_path = NULL; + + resolved_path = gtk_rc_find_pixmap_in_path (gtk_settings_get_default (), NULL, uri->path); + soup_uri_set_path (uri, resolved_path); + g_free (resolved_path), resolved_path = NULL; + + ret = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri), uri = NULL; +#else + char const *given_path; + + g_return_val_if_fail (args, NULL); + + given_path = (char const *) args->data; + resolved_path = gtk_rc_find_pixmap_in_path (gtk_settings_get_default (), NULL, given_path); + ret = g_strdup_printf ("file:///%s", resolved_path); + g_free (resolved_path), resolved_path = NULL; +#endif + + return ret; +} + +static gboolean +color_walk_r (GdkColor *color, + GSList const **args, + char const *function) +{ + double factor; + char const *token; + gboolean ret; + + g_return_val_if_fail (*args && (*args)->data, FALSE); + + if (function) + token = function; + else + token = (char const *) (*args)->data; + + if (0 == g_strcmp0 ("rgb(", token)) { + + double red, green, blue; + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* red */ + red = g_ascii_strtod ((char const *) (*args)->data, NULL); + *args = (*args)->next; if (!*args) return FALSE; + + /* "," */ + if (0 != g_strcmp0(",", (char const *) (*args)->data)) return FALSE; + *args = (*args)->next; if (!*args) return FALSE; + + /* green */ + green = g_ascii_strtod ((char const *) (*args)->data, NULL); + *args = (*args)->next; if (!*args) return FALSE; + + /* "," */ + if (0 != g_strcmp0(",", (char const *) (*args)->data)) return FALSE; + *args = (*args)->next; if (!*args) return FALSE; + + /* blue */ + blue = g_ascii_strtod ((char const *) (*args)->data, NULL); + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + color->red = (guint16) (red * 65535.0); + color->green = (guint16) (green * 65535.0); + color->blue = (guint16) (blue * 65535.0); + + return TRUE; + + } else if (0 == g_strcmp0 ("gtk-color(", token)) { + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* color */ + ret = ccss_gtk_color_lookup ((char const *) (*args)->data, color); + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + return ret; + + } else if (0 == g_strcmp0 ("gtk-mix(", token)) { + + GdkColor color1; + GdkColor color2; + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* factor */ + factor = g_ascii_strtod ((char const *) (*args)->data, NULL); + *args = (*args)->next; if (!*args) return FALSE; + + /* "," */ + if (0 != g_strcmp0(",", (char const *) (*args)->data)) return FALSE; + *args = (*args)->next; if (!*args) return FALSE; + + /* color1 */ + if (!color_walk_r (&color1, args, NULL)) return FALSE; + + /* "," */ + if (0 != g_strcmp0(",", (char const *) (*args)->data)) return FALSE; + *args = (*args)->next; if (!*args) return FALSE; + + /* color2 */ + if (!color_walk_r (&color2, args, NULL)) return FALSE; + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + return ccss_gtk_color_mix (factor, &color1, &color2, color); + + } else if (0 == g_strcmp0 ("gtk-shade(", token)) { + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* factor */ + factor = g_ascii_strtod ((char const *) (*args)->data, NULL); + *args = (*args)->next; if (!*args) return FALSE; + + /* "," */ + if (0 != g_strcmp0(",", (char const *) (*args)->data)) return FALSE; + *args = (*args)->next; if (!*args) return FALSE; + + /* color */ + if (!color_walk_r (color, args, NULL)) return FALSE; + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + return ccss_gtk_color_shade (factor, color); + + } else if (0 == g_strcmp0 ("gtk-darker(", token)) { + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* color */ + if (!color_walk_r (color, args, NULL)) return FALSE; + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + return ccss_gtk_color_shade (0.7, color); + + } else if (0 == g_strcmp0 ("gtk-lighter(", token)) { + + if (!function) { *args = (*args)->next; if (!*args) return FALSE; } + + /* color */ + if (!color_walk_r (color, args, NULL)) return FALSE; + + if (!function) { + /* ")" */ + *args = (*args)->next; if (!*args) return FALSE; + if (0 != g_strcmp0(")", (char const *) (*args)->data)) return FALSE; + } + + return ccss_gtk_color_shade (1.3, color); + + } else { + + /* Color. */ + ret = ccss_gtk_color_lookup (token, color); + *args = (*args)->next; + return ret; + } + + return FALSE; +} + +static char * +dump (GSList const *args) +{ + GSList const *iter; + GString *str; + + str = g_string_new (NULL); + + for ( iter = args; iter != NULL; iter = iter->next) { + g_string_append (str, (char const *) iter->data); + } + + return g_string_free (str, FALSE); +} + +static char * +color (GSList const *args, + void *user_data) +{ + GdkColor result; + gboolean ret; + + g_return_val_if_fail (args && args->data, NULL); + + ret = color_walk_r (&result, &args, "gtk-color("); + if (!ret) { + char *data; + data = dump (args); + g_warning ("Color could not be resolved: `gtk-color(%s)'", data); + return NULL; + } + + return g_strdup_printf ("rgba(%f,%f,%f,1.0)", result.red / 65535.0, + result.green / 65535.0, + result.blue / 65535.0); +} + +static char * +mix (GSList const *args, + void *user_data) +{ + GSList const *iter; + GdkColor result; + gboolean ret; + + g_return_val_if_fail (args && args->data, NULL); + + iter = args; + ret = color_walk_r (&result, &iter, "gtk-mix("); + if (!ret) { + char *data; + data = dump (args); + g_warning ("Color could not be resolved: `gtk-mix(%s)'", data); + return NULL; + } + + return g_strdup_printf ("rgba(%f,%f,%f,1.0)", result.red / 65535.0, + result.green / 65535.0, + result.blue / 65535.0); +} + +static char * +shade (GSList const *args, + void *user_data) +{ + GSList const *iter; + GdkColor result; + gboolean ret; + + g_return_val_if_fail (args && args->data, NULL); + + iter = args; + ret = color_walk_r (&result, &iter, "gtk-shade("); + if (!ret) { + char *data; + data = dump (args); + g_warning ("Color could not be resolved: `gtk-shade(%s)'", data); + return NULL; + } + + return g_strdup_printf ("rgba(%f,%f,%f,1.0)", result.red / 65535.0, + result.green / 65535.0, + result.blue / 65535.0); +} + +static char * +lighter (GSList const *args, + void *user_data) +{ + GSList const *iter; + GdkColor result; + gboolean ret; + + g_return_val_if_fail (args && args->data, NULL); + + iter = args; + ret = color_walk_r (&result, &iter, "gtk-lighter("); + if (!ret) { + char *data; + data = dump (args); + g_warning ("Color could not be resolved: `gtk-lighter(%s)'", data); + return NULL; + } + + return g_strdup_printf ("rgba(%f,%f,%f,1.0)", result.red / 65535.0, + result.green / 65535.0, + result.blue / 65535.0); +} + +static char * +darker (GSList const *args, + void *user_data) +{ + GSList const *iter; + GdkColor result; + gboolean ret; + + g_return_val_if_fail (args && args->data, NULL); + + iter = args; + ret = color_walk_r (&result, &iter, "gtk-darker("); + if (!ret) { + char *data; + data = dump (args); + g_warning ("Color could not be resolved: `gtk-darker(%s)'", data); + return NULL; + } + + return g_strdup_printf ("rgba(%f,%f,%f,1.0)", result.red / 65535.0, + result.green / 65535.0, + result.blue / 65535.0); +} + +static ccss_function_t const _functions[] = +{ + { "url", url, NULL }, + { "gtk-color", color, NULL }, + { "gtk-mix", mix, NULL }, + { "gtk-shade", shade, NULL }, + { "gtk-lighter", lighter, NULL }, + { "gtk-darker", darker, NULL }, + { NULL } +}; + +ccss_function_t const * +ccss_gtk_functions_get_vtable (void) +{ + return _functions; +} + diff --git a/ccss-gtk/ccss-gtk-functions.h b/ccss-gtk/ccss-gtk-functions.h new file mode 100644 index 0000000..b79de14 --- /dev/null +++ b/ccss-gtk/ccss-gtk-functions.h @@ -0,0 +1,40 @@ +/* vim: set ts=8 sw=8 noexpandtab: */ + +/* The Gtk+ CSS Drawing Library. + * Copyright (C) 2008 Robert Staudinger + * + * 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, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CCSS_GTK_FUNCTIONS_H +#define CCSS_GTK_FUNCTIONS_H + +#ifndef CCSS_GTK_H + #ifndef CCSS_GTK_BUILD + #error "Only <ccss-gtk/ccss-gtk.h> can be included directly." + #endif +#endif + +#include <ccss/ccss.h> + +CCSS_BEGIN_DECLS + +ccss_function_t const * ccss_gtk_functions_get_vtable (void); + +CCSS_END_DECLS + +#endif /* CCSS_GTK_FUNCTIONS_H */ + diff --git a/ccss-gtk/ccss-gtk-grammar.c b/ccss-gtk/ccss-gtk-grammar.c index 6b18bec..e1fe3c0 100644 --- a/ccss-gtk/ccss-gtk-grammar.c +++ b/ccss-gtk/ccss-gtk-grammar.c @@ -23,6 +23,7 @@ #include <gtk/gtk.h> #include <ccss-cairo/ccss-cairo.h> #include "ccss-gtk-grammar.h" +#include "ccss-gtk-functions.h" #include "ccss-gtk-property.h" #include "config.h" @@ -49,6 +50,7 @@ ccss_gtk_grammar_create (void) ccss_gtk_property_set_fallback_class (fallback_property_class); ccss_grammar_add_properties (self, ccss_gtk_property_get_property_classes ()); + ccss_grammar_add_functions (self, ccss_gtk_functions_get_vtable ()); return self; } |