From 04da2a61dbee891b1db63e4f71e3da2af9b37a48 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sun, 31 Oct 2010 22:06:48 -0400 Subject: [PATCH] Add StIconColors object, compute in StThemeNode A new StIconColors object is used to efficiently track the colors we need to colorize a symbolic icon. st_theme_node_compute_icon_colors() is added to compute the StIconColors for a theme node. (Refcounting of StIconColors means that we'll typically share the colors object of the parent node.) https://bugzilla.gnome.org/show_bug.cgi?id=633865 --- src/Makefile-st.am | 2 + src/st/st-icon-colors.c | 108 +++++++++++++++++++++++++++++ src/st/st-icon-colors.h | 41 +++++++++++ src/st/st-theme-node-private.h | 1 + src/st/st-theme-node.c | 122 +++++++++++++++++++++++++++++++++ src/st/st-theme-node.h | 3 + 6 files changed, 277 insertions(+) create mode 100644 src/st/st-icon-colors.c create mode 100644 src/st/st-icon-colors.h diff --git a/src/Makefile-st.am b/src/Makefile-st.am index b0272ae38..40d27c56e 100644 --- a/src/Makefile-st.am +++ b/src/Makefile-st.am @@ -80,6 +80,7 @@ st_source_h = \ st/st-focus-manager.h \ st/st-group.h \ st/st-icon.h \ + st/st-icon-colors.h \ st/st-im-text.h \ st/st-label.h \ st/st-overflow-box.h \ @@ -130,6 +131,7 @@ st_source_c = \ st/st-focus-manager.c \ st/st-group.c \ st/st-icon.c \ + st/st-icon-colors.c \ st/st-im-text.c \ st/st-label.c \ st/st-overflow-box.c \ diff --git a/src/st/st-icon-colors.c b/src/st/st-icon-colors.c new file mode 100644 index 000000000..0655246c8 --- /dev/null +++ b/src/st/st-icon-colors.c @@ -0,0 +1,108 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * st-icon-colors.c: Colors for colorizing a symbolic icon + * + * Copyright 2010 Red Hat, Inc. + * Copyright 2010 Florian Müllner + * + * This program 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.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope 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 program. If not, see . + */ + +#include "st-icon-colors.h" + +/** + * st_icon_colors_new: + * + * Creates a new #StIconColors. All colors are initialized to transparent black. + * + * Return value: a newly created #StIconColors. Free with st_icon_colors_unref() + */ +StIconColors * +st_icon_colors_new (void) +{ + StIconColors *colors; + + colors = g_slice_new0 (StIconColors); + colors->ref_count = 1; + + return colors; +} + +/** + * st_icon_colors_ref: + * @colors: a #StIconColors + * + * Atomically increments the reference count of @colors by one. + * + * Returns: the passed in #StIconColors. + */ +StIconColors * +st_icon_colors_ref (StIconColors *colors) +{ + g_return_val_if_fail (colors != NULL, NULL); + g_return_val_if_fail (colors->ref_count > 0, colors); + + g_atomic_int_add ((volatile int *)&colors->ref_count, 1); + return colors; +} + +/** + * st_icon_colors_unref: + * @colors: a #StIconColors + * + * Atomically decrements the reference count of @colors by one. + * If the reference count drops to 0, all memory allocated by the + * #StIconColors is released. + */ +void +st_icon_colors_unref (StIconColors *colors) +{ + g_return_if_fail (colors != NULL); + g_return_if_fail (colors->ref_count > 0); + + if (g_atomic_int_exchange_and_add ((volatile int *)&colors->ref_count, -1) - 1 == 0) + g_slice_free (StIconColors, colors); +} + +/** + * st_icon_colors_copy: + * @colors: a #StIconColors + * + * Creates a new StIconColors structure that is a copy of the passed + * in @colors. You would use this function instead of st_icon_colors_ref() + * if you were planning to change colors in the result. + * + * Returns: a newly created #StIconColors. + */ +StIconColors * +st_icon_colors_copy (StIconColors *colors) +{ + StIconColors *copy; + + g_return_val_if_fail (colors != NULL, NULL); + + copy = st_icon_colors_new (); + + copy->foreground = colors->foreground; + copy->warning = colors->warning; + copy->error = colors->error; + copy->success = colors->success; + + return copy; +} + +G_DEFINE_BOXED_TYPE (StIconColors, + st_icon_colors, + st_icon_colors_ref, + st_icon_colors_unref) diff --git a/src/st/st-icon-colors.h b/src/st/st-icon-colors.h new file mode 100644 index 000000000..b582308a5 --- /dev/null +++ b/src/st/st-icon-colors.h @@ -0,0 +1,41 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +#ifndef __ST_ICON_COLORS__ +#define __ST_ICON_COLORS__ + +#include + +G_BEGIN_DECLS + +#define ST_TYPE_ICON_COLORS (st_icon_colors_get_type ()) + +typedef struct _StIconColors StIconColors; + +/** + * StIconColors: + * @foreground: foreground color + * @warning: color indicating a warning state + * @error: color indicating an error state + * @success: color indicating a successful operation + * + * The #StIconColors structure encapsulates colors for colorizing a symbolic + * icon. + */ +struct _StIconColors { + volatile guint ref_count; + + ClutterColor foreground; + ClutterColor warning; + ClutterColor error; + ClutterColor success; +}; + +GType st_icon_colors_get_type (void) G_GNUC_CONST; + +StIconColors *st_icon_colors_new (void); +StIconColors *st_icon_colors_ref (StIconColors *colors); +void st_icon_colors_unref (StIconColors *colors); +StIconColors *st_icon_colors_copy (StIconColors *colors); + +G_END_DECLS + +#endif /* __ST_ICON_COLORS__ */ diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h index 1ced764f1..7673755e9 100644 --- a/src/st/st-theme-node-private.h +++ b/src/st/st-theme-node-private.h @@ -67,6 +67,7 @@ struct _StThemeNode { StBorderImage *border_image; StShadow *shadow; StShadow *text_shadow; + StIconColors *icon_colors; GType element_type; char *element_id; diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c index d325be0c2..a9d1c2f6d 100644 --- a/src/st/st-theme-node.c +++ b/src/st/st-theme-node.c @@ -36,6 +36,9 @@ static void st_theme_node_finalize (GObject *object); static const ClutterColor BLACK_COLOR = { 0, 0, 0, 0xff }; static const ClutterColor TRANSPARENT_COLOR = { 0, 0, 0, 0 }; +static const ClutterColor DEFAULT_SUCCESS_COLOR = { 0x4e, 0x9a, 0x06, 0xff }; +static const ClutterColor DEFAULT_WARNING_COLOR = { 0xf5, 0x79, 0x3e, 0xff }; +static const ClutterColor DEFAULT_ERROR_COLOR = { 0xcc, 0x00, 0x00, 0xff }; extern gfloat st_slow_down_factor; @@ -2748,6 +2751,125 @@ st_theme_node_get_text_shadow (StThemeNode *node) return result; } +/** + * st_theme_node_get_icon_colors: + * @node: a #StThemeNode + * + * Gets the colors that should be used for colorizing symbolic icons according + * the style of this node. + * + * Return value: (transfer none): the icon colors to use for this theme node + */ +StIconColors * +st_theme_node_get_icon_colors (StThemeNode *node) +{ + /* Foreground here will always be the same as st_theme_node_get_foreground_color(), + * but there's a loss of symmetry and little efficiency win if we try to exploit + * that. */ + + enum { + FOREGROUND = 1 << 0, + WARNING = 1 << 1, + ERROR = 1 << 2, + SUCCESS = 1 << 3 + }; + + gboolean shared_with_parent; + int i; + ClutterColor color = { 0, }; + + guint still_need = FOREGROUND | WARNING | ERROR | SUCCESS; + + g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL); + + if (node->icon_colors) + return node->icon_colors; + + if (node->parent_node) + { + node->icon_colors = st_theme_node_get_icon_colors (node->parent_node); + shared_with_parent = TRUE; + } + else + { + node->icon_colors = st_icon_colors_new (); + node->icon_colors->foreground = BLACK_COLOR; + node->icon_colors->warning = DEFAULT_WARNING_COLOR; + node->icon_colors->error = DEFAULT_ERROR_COLOR; + node->icon_colors->success = DEFAULT_SUCCESS_COLOR; + shared_with_parent = FALSE; + } + + ensure_properties (node); + + for (i = node->n_properties - 1; i >= 0 && still_need != 0; i--) + { + CRDeclaration *decl = node->properties[i]; + GetFromTermResult result = VALUE_NOT_FOUND; + guint found = 0; + + if ((still_need & FOREGROUND) != 0 && + strcmp (decl->property->stryng->str, "color") == 0) + { + found = FOREGROUND; + result = get_color_from_term (node, decl->value, &color); + } + else if ((still_need & WARNING) != 0 && + strcmp (decl->property->stryng->str, "warning-color") == 0) + { + found = WARNING; + result = get_color_from_term (node, decl->value, &color); + } + else if ((still_need & ERROR) != 0 && + strcmp (decl->property->stryng->str, "error-color") == 0) + { + found = ERROR; + result = get_color_from_term (node, decl->value, &color); + } + else if ((still_need & SUCCESS) != 0 && + strcmp (decl->property->stryng->str, "success-color") == 0) + { + found = SUCCESS; + result = get_color_from_term (node, decl->value, &color); + } + + if (result == VALUE_INHERIT) + { + still_need &= ~found; + } + else if (result == VALUE_FOUND) + { + still_need &= ~found; + if (shared_with_parent) + { + node->icon_colors = st_icon_colors_copy (node->icon_colors); + shared_with_parent = FALSE; + } + + switch (found) + { + case FOREGROUND: + node->icon_colors->foreground = color; + break; + case WARNING: + node->icon_colors->warning = color; + break; + case ERROR: + node->icon_colors->error = color; + break; + case SUCCESS: + node->icon_colors->success = color; + break; + } + } + } + + if (shared_with_parent) + st_icon_colors_ref (node->icon_colors); + + return node->icon_colors; +} + static float get_width_inc (StThemeNode *node) { diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h index aeb80d9af..13e0bf63c 100644 --- a/src/st/st-theme-node.h +++ b/src/st/st-theme-node.h @@ -25,6 +25,7 @@ #include #include "st-border-image.h" +#include "st-icon-colors.h" #include "st-shadow.h" G_BEGIN_DECLS @@ -197,6 +198,8 @@ StBorderImage *st_theme_node_get_border_image (StThemeNode *node); StShadow *st_theme_node_get_shadow (StThemeNode *node); StShadow *st_theme_node_get_text_shadow (StThemeNode *node); +StIconColors *st_theme_node_get_icon_colors (StThemeNode *node); + /* Helpers for get_preferred_width()/get_preferred_height() ClutterActor vfuncs */ void st_theme_node_adjust_for_height (StThemeNode *node, float *for_height);