[metacity] libmetacity: add meta-color-spec.[c/h]
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] libmetacity: add meta-color-spec.[c/h]
- Date: Thu, 28 Jan 2016 09:20:34 +0000 (UTC)
commit 3c382734b75c27a6070cb8273dccb21f0355b5cd
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Wed Jan 27 23:08:32 2016 +0200
libmetacity: add meta-color-spec.[c/h]
libmetacity/Makefile.am | 3 +
libmetacity/meta-color-private.h | 33 ++
libmetacity/meta-color-spec.c | 633 ++++++++++++++++++++++++++++++++++++++
libmetacity/meta-color-spec.h | 48 +++
libmetacity/meta-color.c | 1 +
libmetacity/meta-color.h | 4 -
po/POTFILES.in | 2 +-
src/ui/theme-private.h | 69 +----
src/ui/theme.c | 571 ----------------------------------
9 files changed, 721 insertions(+), 643 deletions(-)
---
diff --git a/libmetacity/Makefile.am b/libmetacity/Makefile.am
index 8f89d6a..f2a3e7f 100644
--- a/libmetacity/Makefile.am
+++ b/libmetacity/Makefile.am
@@ -5,6 +5,9 @@ noinst_LTLIBRARIES = libmetacity.la
libmetacity_la_SOURCES = \
meta-color.c \
meta-color.h \
+ meta-color-private.h \
+ meta-color-spec.c \
+ meta-color-spec.h \
meta-hsla.c \
meta-hsla.h \
meta-theme.c \
diff --git a/libmetacity/meta-color-private.h b/libmetacity/meta-color-private.h
new file mode 100644
index 0000000..0e41116
--- /dev/null
+++ b/libmetacity/meta-color-private.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COLOR_PRIVATE_H
+#define META_COLOR_PRIVATE_H
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL
+void meta_color_shade (const GdkRGBA *source,
+ const gdouble factor,
+ GdkRGBA *destination);
+
+G_END_DECLS
+
+#endif
diff --git a/libmetacity/meta-color-spec.c b/libmetacity/meta-color-spec.c
new file mode 100644
index 0000000..5561f71
--- /dev/null
+++ b/libmetacity/meta-color-spec.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "meta-color.h"
+#include "meta-color-private.h"
+#include "meta-color-spec.h"
+#include "meta-theme.h"
+
+enum _MetaColorSpecType
+{
+ META_COLOR_SPEC_BASIC,
+ META_COLOR_SPEC_GTK,
+ META_COLOR_SPEC_GTK_CUSTOM,
+ META_COLOR_SPEC_BLEND,
+ META_COLOR_SPEC_SHADE
+};
+
+enum _MetaGtkColorComponent
+{
+ META_GTK_COLOR_FG,
+ META_GTK_COLOR_BG,
+ META_GTK_COLOR_LIGHT,
+ META_GTK_COLOR_DARK,
+ META_GTK_COLOR_MID,
+ META_GTK_COLOR_TEXT,
+ META_GTK_COLOR_BASE,
+ META_GTK_COLOR_TEXT_AA,
+ META_GTK_COLOR_LAST
+};
+
+struct _MetaColorSpec
+{
+ MetaColorSpecType type;
+ union
+ {
+ struct {
+ GdkRGBA color;
+ } basic;
+ struct {
+ MetaGtkColorComponent component;
+ GtkStateFlags state;
+ } gtk;
+ struct {
+ gchar *color_name;
+ MetaColorSpec *fallback;
+ } gtkcustom;
+ struct {
+ MetaColorSpec *foreground;
+ MetaColorSpec *background;
+ gdouble alpha;
+
+ GdkRGBA color;
+ } blend;
+ struct {
+ MetaColorSpec *base;
+ gdouble factor;
+
+ GdkRGBA color;
+ } shade;
+ } data;
+};
+
+static void
+set_color_from_style (GdkRGBA *color,
+ GtkStyleContext *context,
+ GtkStateFlags state,
+ MetaGtkColorComponent component)
+{
+ GdkRGBA other;
+
+ gtk_style_context_set_state (context, state);
+
+ switch (component)
+ {
+ case META_GTK_COLOR_BG:
+ case META_GTK_COLOR_BASE:
+ meta_color_get_background_color (context, state, color);
+ break;
+
+ case META_GTK_COLOR_FG:
+ case META_GTK_COLOR_TEXT:
+ gtk_style_context_get_color (context, state, color);
+ break;
+
+ case META_GTK_COLOR_TEXT_AA:
+ gtk_style_context_get_color (context, state, color);
+ set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
+
+ color->red = (color->red + other.red) / 2;
+ color->green = (color->green + other.green) / 2;
+ color->blue = (color->blue + other.blue) / 2;
+ break;
+
+ case META_GTK_COLOR_MID:
+ meta_color_get_light_color (context, state, color);
+ meta_color_get_dark_color (context, state, &other);
+
+ color->red = (color->red + other.red) / 2;
+ color->green = (color->green + other.green) / 2;
+ color->blue = (color->blue + other.blue) / 2;
+ break;
+
+ case META_GTK_COLOR_LIGHT:
+ meta_color_get_light_color (context, state, color);
+ break;
+
+ case META_GTK_COLOR_DARK:
+ meta_color_get_dark_color (context, state, color);
+ break;
+
+ case META_GTK_COLOR_LAST:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+color_composite (const GdkRGBA *bg,
+ const GdkRGBA *fg,
+ gdouble alpha,
+ GdkRGBA *color)
+{
+ *color = *bg;
+
+ color->red = color->red + (fg->red - color->red) * alpha;
+ color->green = color->green + (fg->green - color->green) * alpha;
+ color->blue = color->blue + (fg->blue - color->blue) * alpha;
+ color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
+}
+
+static void
+set_custom_color_from_style (GdkRGBA *color,
+ GtkStyleContext *context,
+ const gchar *color_name,
+ MetaColorSpec *fallback)
+{
+ if (!gtk_style_context_lookup_color (context, color_name, color))
+ meta_color_spec_render (fallback, context, color);
+}
+
+static MetaGtkColorComponent
+meta_color_component_from_string (const gchar *str)
+{
+ if (strcmp ("fg", str) == 0)
+ return META_GTK_COLOR_FG;
+ else if (strcmp ("bg", str) == 0)
+ return META_GTK_COLOR_BG;
+ else if (strcmp ("light", str) == 0)
+ return META_GTK_COLOR_LIGHT;
+ else if (strcmp ("dark", str) == 0)
+ return META_GTK_COLOR_DARK;
+ else if (strcmp ("mid", str) == 0)
+ return META_GTK_COLOR_MID;
+ else if (strcmp ("text", str) == 0)
+ return META_GTK_COLOR_TEXT;
+ else if (strcmp ("base", str) == 0)
+ return META_GTK_COLOR_BASE;
+ else if (strcmp ("text_aa", str) == 0)
+ return META_GTK_COLOR_TEXT_AA;
+ else
+ return META_GTK_COLOR_LAST;
+}
+
+MetaColorSpec *
+meta_color_spec_new (MetaColorSpecType type)
+{
+ MetaColorSpec *spec;
+ MetaColorSpec dummy;
+ gint size;
+
+ size = G_STRUCT_OFFSET (MetaColorSpec, data);
+
+ switch (type)
+ {
+ case META_COLOR_SPEC_BASIC:
+ size += sizeof (dummy.data.basic);
+ break;
+
+ case META_COLOR_SPEC_GTK:
+ size += sizeof (dummy.data.gtk);
+ break;
+
+ case META_COLOR_SPEC_GTK_CUSTOM:
+ size += sizeof (dummy.data.gtkcustom);
+ break;
+
+ case META_COLOR_SPEC_BLEND:
+ size += sizeof (dummy.data.blend);
+ break;
+
+ case META_COLOR_SPEC_SHADE:
+ size += sizeof (dummy.data.shade);
+ break;
+
+ default:
+ break;
+ }
+
+ spec = g_malloc0 (size);
+
+ spec->type = type;
+
+ return spec;
+}
+
+MetaColorSpec *
+meta_color_spec_new_from_string (const gchar *str,
+ GError **error)
+{
+ MetaColorSpec *spec;
+
+ spec = NULL;
+
+ if (strncmp (str, "gtk:custom", 10) == 0)
+ {
+ MetaColorSpec *fallback;
+ static gboolean debug_set;
+ static gboolean debug;
+ const gchar *color_name_start;
+ const gchar *fallback_str_start;
+ const gchar *end;
+ gchar *color_name;
+
+ fallback = NULL;
+
+ if (!debug_set)
+ {
+ debug = g_getenv ("METACITY_DISABLE_FALLBACK_COLOR") != NULL;
+ debug_set = TRUE;
+ }
+
+ if (str[10] != '(')
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("GTK custom color specification must have color name and fallback in parentheses,
e.g. gtk:custom(foo,bar); could not parse '%s'"),
+ str);
+ return NULL;
+ }
+
+ color_name_start = str + 11;
+
+ fallback_str_start = color_name_start;
+ while (*fallback_str_start && *fallback_str_start != ',')
+ {
+ if (!(g_ascii_isalnum (*fallback_str_start)
+ || *fallback_str_start == '-' || *fallback_str_start == '_'))
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_
are valid"),
+ *fallback_str_start);
+ return NULL;
+ }
+ fallback_str_start++;
+ }
+ fallback_str_start++;
+
+ end = strrchr (str, ')');
+
+ if (color_name_start == NULL || fallback_str_start == NULL || end == NULL)
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Gtk:custom format is 'gtk:custom(color_name,fallback)', '%s' does not fit the
format"),
+ str);
+ return NULL;
+ }
+
+ if (!debug)
+ {
+ gchar *fallback_str;
+ fallback_str = g_strndup (fallback_str_start, end - fallback_str_start);
+ fallback = meta_color_spec_new_from_string (fallback_str, error);
+ g_free (fallback_str);
+ }
+ else
+ {
+ fallback = meta_color_spec_new_from_string ("pink", error);
+ }
+
+ if (fallback == NULL)
+ return NULL;
+
+ color_name = g_strndup (color_name_start, fallback_str_start - color_name_start - 1);
+
+ spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM);
+ spec->data.gtkcustom.color_name = color_name;
+ spec->data.gtkcustom.fallback = fallback;
+ }
+ else if (strncmp (str, "gtk:", 4) == 0)
+ {
+ const gchar *bracket;
+ const gchar *end_bracket;
+ gchar *tmp;
+ GtkStateFlags state;
+ MetaGtkColorComponent component;
+
+ bracket = str;
+ while (*bracket && *bracket != '[')
+ ++bracket;
+
+ if (*bracket == '\0')
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where
NORMAL is the state; could not parse '%s'"),
+ str);
+ return NULL;
+ }
+
+ end_bracket = bracket;
+ ++end_bracket;
+ while (*end_bracket && *end_bracket != ']')
+ ++end_bracket;
+
+ if (*end_bracket == '\0')
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("GTK color specification must have a close bracket after the state, e.g.
gtk:fg[NORMAL] where NORMAL is the state; could not parse '%s'"),
+ str);
+ return NULL;
+ }
+
+ tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
+ state = meta_gtk_state_from_string (tmp);
+ if (((int) state) == -1)
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Did not understand state '%s' in color specification"),
+ tmp);
+ g_free (tmp);
+ return NULL;
+ }
+ g_free (tmp);
+
+ tmp = g_strndup (str + 4, bracket - str - 4);
+ component = meta_color_component_from_string (tmp);
+ if (component == META_GTK_COLOR_LAST)
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Did not understand color component '%s' in color specification"),
+ tmp);
+ g_free (tmp);
+ return NULL;
+ }
+ g_free (tmp);
+
+ spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
+ spec->data.gtk.state = state;
+ spec->data.gtk.component = component;
+ g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
+ }
+ else if (strncmp (str, "blend/", 6) == 0)
+ {
+ gchar **split;
+ gdouble alpha;
+ gchar *end;
+ MetaColorSpec *fg;
+ MetaColorSpec *bg;
+
+ split = g_strsplit (str, "/", 4);
+
+ if (split[0] == NULL || split[1] == NULL ||
+ split[2] == NULL || split[3] == NULL)
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Blend format is 'blend/bg_color/fg_color/alpha', '%s' does not fit the format"),
+ str);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ alpha = g_ascii_strtod (split[3], &end);
+ if (end == split[3])
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Could not parse alpha value '%s' in blended color"),
+ split[3]);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Alpha value '%s' in blended color is not between 0.0 and 1.0"),
+ split[3]);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ fg = NULL;
+ bg = NULL;
+
+ bg = meta_color_spec_new_from_string (split[1], error);
+ if (bg == NULL)
+ {
+ g_strfreev (split);
+ return NULL;
+ }
+
+ fg = meta_color_spec_new_from_string (split[2], error);
+ if (fg == NULL)
+ {
+ meta_color_spec_free (bg);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ g_strfreev (split);
+
+ spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
+ spec->data.blend.alpha = alpha;
+ spec->data.blend.background = bg;
+ spec->data.blend.foreground = fg;
+ }
+ else if (strncmp (str, "shade/", 6) == 0)
+ {
+ gchar **split;
+ gdouble factor;
+ gchar *end;
+ MetaColorSpec *base;
+
+ split = g_strsplit (str, "/", 3);
+
+ if (split[0] == NULL || split[1] == NULL || split[2] == NULL)
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Shade format is 'shade/base_color/factor', '%s' does not fit the format"),
+ str);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ factor = g_ascii_strtod (split[2], &end);
+ if (end == split[2])
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Could not parse shade factor '%s' in shaded color"),
+ split[2]);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ if (factor < (0.0 - 1e6))
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Shade factor '%s' in shaded color is negative"),
+ split[2]);
+ g_strfreev (split);
+ return NULL;
+ }
+
+ base = meta_color_spec_new_from_string (split[1], error);
+ if (base == NULL)
+ {
+ g_strfreev (split);
+ return NULL;
+ }
+
+ g_strfreev (split);
+
+ spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
+ spec->data.shade.factor = factor;
+ spec->data.shade.base = base;
+ }
+ else
+ {
+ spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
+
+ if (!gdk_rgba_parse (&spec->data.basic.color, str))
+ {
+ g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
+ _("Could not parse color '%s'"), str);
+ meta_color_spec_free (spec);
+ return NULL;
+ }
+ }
+
+ g_assert (spec);
+
+ return spec;
+}
+
+MetaColorSpec *
+meta_color_spec_new_gtk (MetaGtkColorComponent component,
+ GtkStateFlags state)
+{
+ MetaColorSpec *spec;
+
+ spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
+
+ spec->data.gtk.component = component;
+ spec->data.gtk.state = state;
+
+ return spec;
+}
+
+void
+meta_color_spec_free (MetaColorSpec *spec)
+{
+ g_return_if_fail (spec != NULL);
+
+ switch (spec->type)
+ {
+ case META_COLOR_SPEC_BASIC:
+ break;
+
+ case META_COLOR_SPEC_GTK:
+ break;
+
+ case META_COLOR_SPEC_GTK_CUSTOM:
+ if (spec->data.gtkcustom.color_name)
+ g_free (spec->data.gtkcustom.color_name);
+ if (spec->data.gtkcustom.fallback)
+ meta_color_spec_free (spec->data.gtkcustom.fallback);
+ break;
+
+ case META_COLOR_SPEC_BLEND:
+ if (spec->data.blend.foreground)
+ meta_color_spec_free (spec->data.blend.foreground);
+ if (spec->data.blend.background)
+ meta_color_spec_free (spec->data.blend.background);
+ break;
+
+ case META_COLOR_SPEC_SHADE:
+ if (spec->data.shade.base)
+ meta_color_spec_free (spec->data.shade.base);
+ break;
+
+ default:
+ break;
+ }
+
+ g_free (spec);
+}
+
+void
+meta_color_spec_render (MetaColorSpec *spec,
+ GtkStyleContext *context,
+ GdkRGBA *color)
+{
+ g_return_if_fail (spec != NULL);
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ switch (spec->type)
+ {
+ case META_COLOR_SPEC_BASIC:
+ *color = spec->data.basic.color;
+ break;
+
+ case META_COLOR_SPEC_GTK:
+ set_color_from_style (color, context, spec->data.gtk.state,
+ spec->data.gtk.component);
+ break;
+
+ case META_COLOR_SPEC_GTK_CUSTOM:
+ set_custom_color_from_style (color, context,
+ spec->data.gtkcustom.color_name,
+ spec->data.gtkcustom.fallback);
+ break;
+
+ case META_COLOR_SPEC_BLEND:
+ {
+ GdkRGBA bg;
+ GdkRGBA fg;
+
+ meta_color_spec_render (spec->data.blend.background, context, &bg);
+ meta_color_spec_render (spec->data.blend.foreground, context, &fg);
+
+ color_composite (&bg, &fg, spec->data.blend.alpha,
+ &spec->data.blend.color);
+
+ *color = spec->data.blend.color;
+ }
+ break;
+
+ case META_COLOR_SPEC_SHADE:
+ {
+ meta_color_spec_render (spec->data.shade.base, context,
+ &spec->data.shade.color);
+
+ meta_color_shade (&spec->data.shade.color, spec->data.shade.factor,
+ &spec->data.shade.color);
+
+ *color = spec->data.shade.color;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+GtkStateFlags
+meta_gtk_state_from_string (const gchar *str)
+{
+ if (g_ascii_strcasecmp ("normal", str) == 0)
+ return GTK_STATE_FLAG_NORMAL;
+ else if (g_ascii_strcasecmp ("prelight", str) == 0)
+ return GTK_STATE_FLAG_PRELIGHT;
+ else if (g_ascii_strcasecmp ("active", str) == 0)
+ return GTK_STATE_FLAG_ACTIVE;
+ else if (g_ascii_strcasecmp ("selected", str) == 0)
+ return GTK_STATE_FLAG_SELECTED;
+ else if (g_ascii_strcasecmp ("insensitive", str) == 0)
+ return GTK_STATE_FLAG_INSENSITIVE;
+ else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
+ return GTK_STATE_FLAG_INCONSISTENT;
+ else if (g_ascii_strcasecmp ("focused", str) == 0)
+ return GTK_STATE_FLAG_FOCUSED;
+ else if (g_ascii_strcasecmp ("backdrop", str) == 0)
+ return GTK_STATE_FLAG_BACKDROP;
+ else
+ return -1;
+}
diff --git a/libmetacity/meta-color-spec.h b/libmetacity/meta-color-spec.h
new file mode 100644
index 0000000..fb4d2e5
--- /dev/null
+++ b/libmetacity/meta-color-spec.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COLOR_SPEC_H
+#define META_COLOR_SPEC_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef enum _MetaColorSpecType MetaColorSpecType;
+typedef enum _MetaGtkColorComponent MetaGtkColorComponent;
+typedef struct _MetaColorSpec MetaColorSpec;
+
+MetaColorSpec *meta_color_spec_new (MetaColorSpecType type);
+
+MetaColorSpec *meta_color_spec_new_from_string (const gchar *str,
+ GError **error);
+
+MetaColorSpec *meta_color_spec_new_gtk (MetaGtkColorComponent component,
+ GtkStateFlags state);
+
+void meta_color_spec_free (MetaColorSpec *spec);
+
+void meta_color_spec_render (MetaColorSpec *spec,
+ GtkStyleContext *context,
+ GdkRGBA *color);
+
+GtkStateFlags meta_gtk_state_from_string (const gchar *str);
+
+G_END_DECLS
+
+#endif
diff --git a/libmetacity/meta-color.c b/libmetacity/meta-color.c
index 17fe213..ff64ecd 100644
--- a/libmetacity/meta-color.c
+++ b/libmetacity/meta-color.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "meta-hsla.h"
+#include "meta-color-private.h"
#include "meta-color.h"
#define LIGHTNESS_MULT 1.3
diff --git a/libmetacity/meta-color.h b/libmetacity/meta-color.h
index effeb18..9b153d1 100644
--- a/libmetacity/meta-color.h
+++ b/libmetacity/meta-color.h
@@ -23,10 +23,6 @@
G_BEGIN_DECLS
-void meta_color_shade (const GdkRGBA *source,
- const gdouble factor,
- GdkRGBA *destination);
-
void meta_color_get_background_color (GtkStyleContext *context,
GtkStateFlags state,
GdkRGBA *color);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6e31bc4..d768852 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,6 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
+libmetacity/meta-color-spec.c
src/50-metacity-navigation.xml.in
src/50-metacity-system.xml.in
src/50-metacity-windows.xml.in
@@ -28,4 +29,3 @@ src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/ui/theme-viewer.c
-
diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h
index 66df5a5..de73200 100644
--- a/src/ui/theme-private.h
+++ b/src/ui/theme-private.h
@@ -18,6 +18,8 @@
#ifndef META_THEME_PRIVATE_H
#define META_THEME_PRIVATE_H
+#include <libmetacity/meta-color-spec.h>
+
#include "boxes.h"
#include "gradient.h"
#include "theme.h"
@@ -25,7 +27,6 @@
G_BEGIN_DECLS
typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
-typedef struct _MetaColorSpec MetaColorSpec;
typedef struct _MetaDrawInfo MetaDrawInfo;
typedef struct _MetaDrawOp MetaDrawOp;
typedef struct _MetaDrawOpList MetaDrawOpList;
@@ -335,60 +336,6 @@ struct _MetaDrawInfo
const MetaFrameGeometry *fgeom;
};
-typedef enum
-{
- META_GTK_COLOR_FG,
- META_GTK_COLOR_BG,
- META_GTK_COLOR_LIGHT,
- META_GTK_COLOR_DARK,
- META_GTK_COLOR_MID,
- META_GTK_COLOR_TEXT,
- META_GTK_COLOR_BASE,
- META_GTK_COLOR_TEXT_AA,
- META_GTK_COLOR_LAST
-} MetaGtkColorComponent;
-
-typedef enum
-{
- META_COLOR_SPEC_BASIC,
- META_COLOR_SPEC_GTK,
- META_COLOR_SPEC_GTK_CUSTOM,
- META_COLOR_SPEC_BLEND,
- META_COLOR_SPEC_SHADE
-} MetaColorSpecType;
-
-struct _MetaColorSpec
-{
- MetaColorSpecType type;
- union
- {
- struct {
- GdkRGBA color;
- } basic;
- struct {
- MetaGtkColorComponent component;
- GtkStateFlags state;
- } gtk;
- struct {
- char *color_name;
- MetaColorSpec *fallback;
- } gtkcustom;
- struct {
- MetaColorSpec *foreground;
- MetaColorSpec *background;
- double alpha;
-
- GdkRGBA color;
- } blend;
- struct {
- MetaColorSpec *base;
- double factor;
-
- GdkRGBA color;
- } shade;
- } data;
-};
-
struct _MetaPositionExprEnv
{
MetaRectangle rect;
@@ -741,16 +688,6 @@ void meta_frame_layout_unref (MetaFrameLayout
gboolean meta_frame_layout_validate (const MetaFrameLayout *layout,
GError **error);
-MetaColorSpec *meta_color_spec_new (MetaColorSpecType type);
-MetaColorSpec *meta_color_spec_new_from_string (const char *str,
- GError **err);
-MetaColorSpec *meta_color_spec_new_gtk (MetaGtkColorComponent component,
- GtkStateFlags state);
-void meta_color_spec_free (MetaColorSpec *spec);
-void meta_color_spec_render (MetaColorSpec *spec,
- GtkStyleContext *style_gtk,
- GdkRGBA *color);
-
MetaDrawSpec *meta_draw_spec_new (MetaTheme *theme,
const char *expr,
GError **error);
@@ -854,8 +791,6 @@ gboolean meta_theme_lookup_color_constant (MetaTheme
const char *name,
char **value);
-GtkStateFlags meta_gtk_state_from_string (const char *str);
-
PangoFontDescription *meta_gtk_widget_get_font_desc (GtkWidget *widget,
double scale,
const PangoFontDescription *override);
diff --git a/src/ui/theme.c b/src/ui/theme.c
index 946e73d..db630ec 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -162,19 +162,6 @@ colorize_pixbuf (GdkPixbuf *orig,
return pixbuf;
}
-static void
-color_composite (const GdkRGBA *bg,
- const GdkRGBA *fg,
- double alpha,
- GdkRGBA *color)
-{
- *color = *bg;
- color->red = color->red + (fg->red - color->red) * alpha;
- color->green = color->green + (fg->green - color->green) * alpha;
- color->blue = color->blue + (fg->blue - color->blue) * alpha;
- color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
-}
-
/**
* Sets all the fields of a border to dummy values.
*
@@ -1265,541 +1252,6 @@ meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
g_free (spec);
}
-MetaColorSpec*
-meta_color_spec_new (MetaColorSpecType type)
-{
- MetaColorSpec *spec;
- MetaColorSpec dummy;
- int size;
-
- size = G_STRUCT_OFFSET (MetaColorSpec, data);
-
- switch (type)
- {
- case META_COLOR_SPEC_BASIC:
- size += sizeof (dummy.data.basic);
- break;
-
- case META_COLOR_SPEC_GTK:
- size += sizeof (dummy.data.gtk);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- size += sizeof (dummy.data.gtkcustom);
- break;
-
- case META_COLOR_SPEC_BLEND:
- size += sizeof (dummy.data.blend);
- break;
-
- case META_COLOR_SPEC_SHADE:
- size += sizeof (dummy.data.shade);
- break;
-
- default:
- break;
- }
-
- spec = g_malloc0 (size);
-
- spec->type = type;
-
- return spec;
-}
-
-void
-meta_color_spec_free (MetaColorSpec *spec)
-{
- g_return_if_fail (spec != NULL);
-
- switch (spec->type)
- {
- case META_COLOR_SPEC_BASIC:
- DEBUG_FILL_STRUCT (&spec->data.basic);
- break;
-
- case META_COLOR_SPEC_GTK:
- DEBUG_FILL_STRUCT (&spec->data.gtk);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- if (spec->data.gtkcustom.color_name)
- g_free (spec->data.gtkcustom.color_name);
- if (spec->data.gtkcustom.fallback)
- meta_color_spec_free (spec->data.gtkcustom.fallback);
- DEBUG_FILL_STRUCT (&spec->data.gtkcustom);
- break;
-
- case META_COLOR_SPEC_BLEND:
- if (spec->data.blend.foreground)
- meta_color_spec_free (spec->data.blend.foreground);
- if (spec->data.blend.background)
- meta_color_spec_free (spec->data.blend.background);
- DEBUG_FILL_STRUCT (&spec->data.blend);
- break;
-
- case META_COLOR_SPEC_SHADE:
- if (spec->data.shade.base)
- meta_color_spec_free (spec->data.shade.base);
- DEBUG_FILL_STRUCT (&spec->data.shade);
- break;
-
- default:
- break;
- }
-
- g_free (spec);
-}
-
-static MetaGtkColorComponent
-meta_color_component_from_string (const char *str)
-{
- if (strcmp ("fg", str) == 0)
- return META_GTK_COLOR_FG;
- else if (strcmp ("bg", str) == 0)
- return META_GTK_COLOR_BG;
- else if (strcmp ("light", str) == 0)
- return META_GTK_COLOR_LIGHT;
- else if (strcmp ("dark", str) == 0)
- return META_GTK_COLOR_DARK;
- else if (strcmp ("mid", str) == 0)
- return META_GTK_COLOR_MID;
- else if (strcmp ("text", str) == 0)
- return META_GTK_COLOR_TEXT;
- else if (strcmp ("base", str) == 0)
- return META_GTK_COLOR_BASE;
- else if (strcmp ("text_aa", str) == 0)
- return META_GTK_COLOR_TEXT_AA;
- else
- return META_GTK_COLOR_LAST;
-}
-
-MetaColorSpec*
-meta_color_spec_new_from_string (const char *str,
- GError **err)
-{
- MetaColorSpec *spec;
-
- spec = NULL;
-
- if (strncmp (str, "gtk:custom", 10) == 0)
- {
- const char *color_name_start, *fallback_str_start, *end;
- char *color_name;
- MetaColorSpec *fallback = NULL;
- static gboolean debug, debug_set = FALSE;
-
- if (!debug_set)
- {
- debug = g_getenv ("METACITY_DISABLE_FALLBACK_COLOR") != NULL;
- debug_set = TRUE;
- }
-
- if (str[10] != '(')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK custom color specification must have color name and fallback in parentheses,
e.g. gtk:custom(foo,bar); could not parse \"%s\""),
- str);
- return NULL;
- }
-
- color_name_start = str + 11;
-
- fallback_str_start = color_name_start;
- while (*fallback_str_start && *fallback_str_start != ',')
- {
- if (!(g_ascii_isalnum (*fallback_str_start)
- || *fallback_str_start == '-'
- || *fallback_str_start == '_'))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_
are valid"),
- *fallback_str_start);
- return NULL;
- }
- fallback_str_start++;
- }
- fallback_str_start++;
-
- end = strrchr (str, ')');
-
- if (color_name_start == NULL || fallback_str_start == NULL || end == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the
format"),
- str);
- return NULL;
- }
-
- if (!debug)
- {
- char *fallback_str;
- fallback_str = g_strndup (fallback_str_start,
- end - fallback_str_start);
- fallback = meta_color_spec_new_from_string (fallback_str, err);
- g_free (fallback_str);
- }
- else
- {
- fallback = meta_color_spec_new_from_string ("pink", err);
- }
-
- if (fallback == NULL)
- return NULL;
-
- color_name = g_strndup (color_name_start, fallback_str_start - color_name_start - 1);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM);
- spec->data.gtkcustom.color_name = color_name;
- spec->data.gtkcustom.fallback = fallback;
- }
- else if (strncmp (str, "gtk:", 4) == 0)
- {
- /* GTK color */
- const char *bracket;
- const char *end_bracket;
- char *tmp;
- GtkStateFlags state;
- MetaGtkColorComponent component;
-
- bracket = str;
- while (*bracket && *bracket != '[')
- ++bracket;
-
- if (*bracket == '\0')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where
NORMAL is the state; could not parse \"%s\""),
- str);
- return NULL;
- }
-
- end_bracket = bracket;
- ++end_bracket;
- while (*end_bracket && *end_bracket != ']')
- ++end_bracket;
-
- if (*end_bracket == '\0')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK color specification must have a close bracket after the state, e.g.
gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""),
- str);
- return NULL;
- }
-
- tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
- state = meta_gtk_state_from_string (tmp);
- if (((int) state) == -1)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Did not understand state \"%s\" in color specification"),
- tmp);
- g_free (tmp);
- return NULL;
- }
- g_free (tmp);
-
- tmp = g_strndup (str + 4, bracket - str - 4);
- component = meta_color_component_from_string (tmp);
- if (component == META_GTK_COLOR_LAST)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Did not understand color component \"%s\" in color specification"),
- tmp);
- g_free (tmp);
- return NULL;
- }
- g_free (tmp);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
- spec->data.gtk.state = state;
- spec->data.gtk.component = component;
- g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
- }
- else if (strncmp (str, "blend/", 6) == 0)
- {
- /* blend */
- char **split;
- double alpha;
- char *end;
- MetaColorSpec *fg;
- MetaColorSpec *bg;
-
- split = g_strsplit (str, "/", 4);
-
- if (split[0] == NULL || split[1] == NULL ||
- split[2] == NULL || split[3] == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the
format"),
- str);
- g_strfreev (split);
- return NULL;
- }
-
- alpha = g_ascii_strtod (split[3], &end);
- if (end == split[3])
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse alpha value \"%s\" in blended color"),
- split[3]);
- g_strfreev (split);
- return NULL;
- }
-
- if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Alpha value \"%s\" in blended color is not between 0.0 and 1.0"),
- split[3]);
- g_strfreev (split);
- return NULL;
- }
-
- fg = NULL;
- bg = NULL;
-
- bg = meta_color_spec_new_from_string (split[1], err);
- if (bg == NULL)
- {
- g_strfreev (split);
- return NULL;
- }
-
- fg = meta_color_spec_new_from_string (split[2], err);
- if (fg == NULL)
- {
- meta_color_spec_free (bg);
- g_strfreev (split);
- return NULL;
- }
-
- g_strfreev (split);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
- spec->data.blend.alpha = alpha;
- spec->data.blend.background = bg;
- spec->data.blend.foreground = fg;
- }
- else if (strncmp (str, "shade/", 6) == 0)
- {
- /* shade */
- char **split;
- double factor;
- char *end;
- MetaColorSpec *base;
-
- split = g_strsplit (str, "/", 3);
-
- if (split[0] == NULL || split[1] == NULL ||
- split[2] == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"),
- str);
- g_strfreev (split);
- return NULL;
- }
-
- factor = g_ascii_strtod (split[2], &end);
- if (end == split[2])
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse shade factor \"%s\" in shaded color"),
- split[2]);
- g_strfreev (split);
- return NULL;
- }
-
- if (factor < (0.0 - 1e6))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Shade factor \"%s\" in shaded color is negative"),
- split[2]);
- g_strfreev (split);
- return NULL;
- }
-
- base = NULL;
-
- base = meta_color_spec_new_from_string (split[1], err);
- if (base == NULL)
- {
- g_strfreev (split);
- return NULL;
- }
-
- g_strfreev (split);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
- spec->data.shade.factor = factor;
- spec->data.shade.base = base;
- }
- else
- {
- spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
-
- if (!gdk_rgba_parse (&spec->data.basic.color, str))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse color \"%s\""),
- str);
- meta_color_spec_free (spec);
- return NULL;
- }
- }
-
- g_assert (spec);
-
- return spec;
-}
-
-MetaColorSpec*
-meta_color_spec_new_gtk (MetaGtkColorComponent component,
- GtkStateFlags state)
-{
- MetaColorSpec *spec;
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
-
- spec->data.gtk.component = component;
- spec->data.gtk.state = state;
-
- return spec;
-}
-
-static void
-meta_set_color_from_style (GdkRGBA *color,
- GtkStyleContext *context,
- GtkStateFlags state,
- MetaGtkColorComponent component)
-{
- GdkRGBA other;
-
- gtk_style_context_set_state (context, state);
-
- switch (component)
- {
- case META_GTK_COLOR_BG:
- case META_GTK_COLOR_BASE:
- meta_color_get_background_color (context, state, color);
- break;
- case META_GTK_COLOR_FG:
- case META_GTK_COLOR_TEXT:
- gtk_style_context_get_color (context, state, color);
- break;
- case META_GTK_COLOR_TEXT_AA:
- gtk_style_context_get_color (context, state, color);
- meta_set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
-
- color->red = (color->red + other.red) / 2;
- color->green = (color->green + other.green) / 2;
- color->blue = (color->blue + other.blue) / 2;
- break;
- case META_GTK_COLOR_MID:
- meta_color_get_light_color (context, state, color);
- meta_color_get_dark_color (context, state, &other);
-
- color->red = (color->red + other.red) / 2;
- color->green = (color->green + other.green) / 2;
- color->blue = (color->blue + other.blue) / 2;
- break;
- case META_GTK_COLOR_LIGHT:
- meta_color_get_light_color (context, state, color);
- break;
- case META_GTK_COLOR_DARK:
- meta_color_get_dark_color (context, state, color);
- break;
- case META_GTK_COLOR_LAST:
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-meta_set_custom_color_from_style (GdkRGBA *color,
- GtkStyleContext *context,
- char *color_name,
- MetaColorSpec *fallback)
-{
- if (!gtk_style_context_lookup_color (context, color_name, color))
- meta_color_spec_render (fallback, context, color);
-}
-
-void
-meta_color_spec_render (MetaColorSpec *spec,
- GtkStyleContext *context,
- GdkRGBA *color)
-{
- g_return_if_fail (spec != NULL);
- g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
- switch (spec->type)
- {
- case META_COLOR_SPEC_BASIC:
- *color = spec->data.basic.color;
- break;
-
- case META_COLOR_SPEC_GTK:
- meta_set_color_from_style (color,
- context,
- spec->data.gtk.state,
- spec->data.gtk.component);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- meta_set_custom_color_from_style (color,
- context,
- spec->data.gtkcustom.color_name,
- spec->data.gtkcustom.fallback);
- break;
-
- case META_COLOR_SPEC_BLEND:
- {
- GdkRGBA bg, fg;
-
- meta_color_spec_render (spec->data.blend.background, context, &bg);
- meta_color_spec_render (spec->data.blend.foreground, context, &fg);
-
- color_composite (&bg, &fg, spec->data.blend.alpha,
- &spec->data.blend.color);
-
- *color = spec->data.blend.color;
- }
- break;
-
- case META_COLOR_SPEC_SHADE:
- {
- meta_color_spec_render (spec->data.shade.base, context,
- &spec->data.shade.color);
-
- meta_color_shade (&spec->data.shade.color, spec->data.shade.factor,
- &spec->data.shade.color);
-
- *color = spec->data.shade.color;
- }
- break;
-
- default:
- break;
- }
-}
-
/**
* Represents an operation as a string.
*
@@ -6527,29 +5979,6 @@ meta_frame_type_from_string (const char *str)
return META_FRAME_TYPE_LAST;
}
-GtkStateFlags
-meta_gtk_state_from_string (const char *str)
-{
- if (g_ascii_strcasecmp ("normal", str) == 0)
- return GTK_STATE_FLAG_NORMAL;
- else if (g_ascii_strcasecmp ("prelight", str) == 0)
- return GTK_STATE_FLAG_PRELIGHT;
- else if (g_ascii_strcasecmp ("active", str) == 0)
- return GTK_STATE_FLAG_ACTIVE;
- else if (g_ascii_strcasecmp ("selected", str) == 0)
- return GTK_STATE_FLAG_SELECTED;
- else if (g_ascii_strcasecmp ("insensitive", str) == 0)
- return GTK_STATE_FLAG_INSENSITIVE;
- else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
- return GTK_STATE_FLAG_INCONSISTENT;
- else if (g_ascii_strcasecmp ("focused", str) == 0)
- return GTK_STATE_FLAG_FOCUSED;
- else if (g_ascii_strcasecmp ("backdrop", str) == 0)
- return GTK_STATE_FLAG_BACKDROP;
- else
- return -1; /* hack */
-}
-
/**
* Returns the earliest version of the theme format which required support
* for a particular button. (For example, "shade" first appeared in v2, and
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]