Blame libmetacity/meta-color-spec.c

Packit 5e0819
/*
Packit 5e0819
 * Copyright (C) 2001 Havoc Pennington
Packit 5e0819
 * Copyright (C) 2016 Alberts Muktupāvels
Packit 5e0819
 *
Packit 5e0819
 * This program is free software: you can redistribute it and/or modify
Packit 5e0819
 * it under the terms of the GNU General Public License as published by
Packit 5e0819
 * the Free Software Foundation, either version 2 of the License, or
Packit 5e0819
 * (at your option) any later version.
Packit 5e0819
 *
Packit 5e0819
 * This program is distributed in the hope that it will be useful,
Packit 5e0819
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e0819
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Packit 5e0819
 * GNU General Public License for more details.
Packit 5e0819
 *
Packit 5e0819
 * You should have received a copy of the GNU General Public License
Packit 5e0819
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Packit 5e0819
 */
Packit 5e0819
Packit 5e0819
#include "config.h"
Packit 5e0819
Packit 5e0819
#include <glib/gi18n-lib.h>
Packit 5e0819
Packit 5e0819
#include "meta-color.h"
Packit 5e0819
#include "meta-color-private.h"
Packit 5e0819
#include "meta-color-spec-private.h"
Packit 5e0819
#include "meta-theme.h"
Packit 5e0819
Packit 5e0819
enum _MetaColorSpecType
Packit 5e0819
{
Packit 5e0819
  META_COLOR_SPEC_BASIC,
Packit 5e0819
  META_COLOR_SPEC_GTK,
Packit 5e0819
  META_COLOR_SPEC_GTK_CUSTOM,
Packit 5e0819
  META_COLOR_SPEC_BLEND,
Packit 5e0819
  META_COLOR_SPEC_SHADE
Packit 5e0819
};
Packit 5e0819
Packit 5e0819
enum _MetaGtkColorComponent
Packit 5e0819
{
Packit 5e0819
  META_GTK_COLOR_FG,
Packit 5e0819
  META_GTK_COLOR_BG,
Packit 5e0819
  META_GTK_COLOR_LIGHT,
Packit 5e0819
  META_GTK_COLOR_DARK,
Packit 5e0819
  META_GTK_COLOR_MID,
Packit 5e0819
  META_GTK_COLOR_TEXT,
Packit 5e0819
  META_GTK_COLOR_BASE,
Packit 5e0819
  META_GTK_COLOR_TEXT_AA,
Packit 5e0819
  META_GTK_COLOR_LAST
Packit 5e0819
};
Packit 5e0819
Packit 5e0819
struct _MetaColorSpec
Packit 5e0819
{
Packit 5e0819
  MetaColorSpecType type;
Packit 5e0819
  union
Packit 5e0819
  {
Packit 5e0819
    struct {
Packit 5e0819
      GdkRGBA color;
Packit 5e0819
    } basic;
Packit 5e0819
    struct {
Packit 5e0819
      MetaGtkColorComponent component;
Packit 5e0819
      GtkStateFlags         state;
Packit 5e0819
    } gtk;
Packit 5e0819
    struct {
Packit 5e0819
      gchar         *color_name;
Packit 5e0819
      MetaColorSpec *fallback;
Packit 5e0819
    } gtkcustom;
Packit 5e0819
    struct {
Packit 5e0819
      MetaColorSpec *foreground;
Packit 5e0819
      MetaColorSpec *background;
Packit 5e0819
      gdouble        alpha;
Packit 5e0819
Packit 5e0819
      GdkRGBA        color;
Packit 5e0819
    } blend;
Packit 5e0819
    struct {
Packit 5e0819
      MetaColorSpec *base;
Packit 5e0819
      gdouble        factor;
Packit 5e0819
Packit 5e0819
      GdkRGBA        color;
Packit 5e0819
    } shade;
Packit 5e0819
  } data;
Packit 5e0819
};
Packit 5e0819
Packit 5e0819
static void
Packit 5e0819
set_color_from_style (GdkRGBA               *color,
Packit 5e0819
                      GtkStyleContext       *context,
Packit 5e0819
                      GtkStateFlags          state,
Packit 5e0819
                      MetaGtkColorComponent  component)
Packit 5e0819
{
Packit 5e0819
  GdkRGBA other;
Packit 5e0819
Packit 5e0819
  gtk_style_context_set_state (context, state);
Packit 5e0819
Packit 5e0819
  switch (component)
Packit 5e0819
    {
Packit 5e0819
      case META_GTK_COLOR_BG:
Packit 5e0819
      case META_GTK_COLOR_BASE:
Packit 5e0819
        meta_color_get_background_color (context, state, color);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_FG:
Packit 5e0819
      case META_GTK_COLOR_TEXT:
Packit 5e0819
        gtk_style_context_get_color (context, state, color);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_TEXT_AA:
Packit 5e0819
        gtk_style_context_get_color (context, state, color);
Packit 5e0819
        set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
Packit 5e0819
Packit 5e0819
        color->red = (color->red + other.red) / 2;
Packit 5e0819
        color->green = (color->green + other.green) / 2;
Packit 5e0819
        color->blue = (color->blue + other.blue) / 2;
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_MID:
Packit 5e0819
        meta_color_get_light_color (context, state, color);
Packit 5e0819
        meta_color_get_dark_color (context, state, &other);
Packit 5e0819
Packit 5e0819
        color->red = (color->red + other.red) / 2;
Packit 5e0819
        color->green = (color->green + other.green) / 2;
Packit 5e0819
        color->blue = (color->blue + other.blue) / 2;
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_LIGHT:
Packit 5e0819
        meta_color_get_light_color (context, state, color);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_DARK:
Packit 5e0819
        meta_color_get_dark_color (context, state, color);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_GTK_COLOR_LAST:
Packit 5e0819
      default:
Packit 5e0819
        g_assert_not_reached ();
Packit 5e0819
        break;
Packit 5e0819
    }
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
static void
Packit 5e0819
color_composite (const GdkRGBA *bg,
Packit 5e0819
                 const GdkRGBA *fg,
Packit 5e0819
                 gdouble        alpha,
Packit 5e0819
                 GdkRGBA       *color)
Packit 5e0819
{
Packit 5e0819
  *color = *bg;
Packit 5e0819
Packit 5e0819
  color->red = color->red + (fg->red - color->red) * alpha;
Packit 5e0819
  color->green = color->green + (fg->green - color->green) * alpha;
Packit 5e0819
  color->blue = color->blue + (fg->blue - color->blue) * alpha;
Packit 5e0819
  color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
static void
Packit 5e0819
set_custom_color_from_style (GdkRGBA         *color,
Packit 5e0819
                             GtkStyleContext *context,
Packit 5e0819
                             const gchar     *color_name,
Packit 5e0819
                             MetaColorSpec   *fallback)
Packit 5e0819
{
Packit 5e0819
  if (!gtk_style_context_lookup_color (context, color_name, color))
Packit 5e0819
    meta_color_spec_render (fallback, context, color);
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
static MetaGtkColorComponent
Packit 5e0819
meta_color_component_from_string (const gchar *str)
Packit 5e0819
{
Packit 5e0819
  if (strcmp ("fg", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_FG;
Packit 5e0819
  else if (strcmp ("bg", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_BG;
Packit 5e0819
  else if (strcmp ("light", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_LIGHT;
Packit 5e0819
  else if (strcmp ("dark", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_DARK;
Packit 5e0819
  else if (strcmp ("mid", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_MID;
Packit 5e0819
  else if (strcmp ("text", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_TEXT;
Packit 5e0819
  else if (strcmp ("base", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_BASE;
Packit 5e0819
  else if (strcmp ("text_aa", str) == 0)
Packit 5e0819
    return META_GTK_COLOR_TEXT_AA;
Packit 5e0819
  else
Packit 5e0819
    return META_GTK_COLOR_LAST;
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
MetaColorSpec *
Packit 5e0819
meta_color_spec_new (MetaColorSpecType type)
Packit 5e0819
{
Packit 5e0819
  MetaColorSpec *spec;
Packit 5e0819
  MetaColorSpec dummy;
Packit 5e0819
  gint size;
Packit 5e0819
Packit 5e0819
  size = G_STRUCT_OFFSET (MetaColorSpec, data);
Packit 5e0819
Packit 5e0819
  switch (type)
Packit 5e0819
    {
Packit 5e0819
      case META_COLOR_SPEC_BASIC:
Packit 5e0819
        size += sizeof (dummy.data.basic);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK:
Packit 5e0819
        size += sizeof (dummy.data.gtk);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK_CUSTOM:
Packit 5e0819
        size += sizeof (dummy.data.gtkcustom);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_BLEND:
Packit 5e0819
        size += sizeof (dummy.data.blend);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_SHADE:
Packit 5e0819
        size += sizeof (dummy.data.shade);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      default:
Packit 5e0819
        break;
Packit 5e0819
    }
Packit 5e0819
Packit 5e0819
  spec = g_malloc0 (size);
Packit 5e0819
Packit 5e0819
  spec->type = type;
Packit 5e0819
Packit 5e0819
  return spec;
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
MetaColorSpec *
Packit 5e0819
meta_color_spec_new_from_string (const gchar  *str,
Packit 5e0819
                                 GError      **error)
Packit 5e0819
{
Packit 5e0819
  MetaColorSpec *spec;
Packit 5e0819
Packit 5e0819
  spec = NULL;
Packit 5e0819
Packit 5e0819
  if (strncmp (str, "gtk:custom", 10) == 0)
Packit 5e0819
    {
Packit 5e0819
      const gchar *color_name_start;
Packit 5e0819
      const gchar *fallback_str_start;
Packit 5e0819
      const gchar *end;
Packit 5e0819
      gchar *fallback_str;
Packit 5e0819
      MetaColorSpec *fallback;
Packit 5e0819
      gchar *color_name;
Packit 5e0819
Packit 5e0819
      if (str[10] != '(')
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("GTK custom color specification must have color name and fallback in parentheses, e.g. gtk:custom(foo,bar); could not parse '%s'"),
Packit 5e0819
                       str);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      color_name_start = str + 11;
Packit 5e0819
Packit 5e0819
      fallback_str_start = color_name_start;
Packit 5e0819
      while (*fallback_str_start && *fallback_str_start != ',')
Packit 5e0819
        {
Packit 5e0819
          if (!(g_ascii_isalnum (*fallback_str_start)
Packit 5e0819
                || *fallback_str_start == '-' || *fallback_str_start == '_'))
Packit 5e0819
            {
Packit 5e0819
              g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                           _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"),
Packit 5e0819
                           *fallback_str_start);
Packit 5e0819
              return NULL;
Packit 5e0819
            }
Packit 5e0819
          fallback_str_start++;
Packit 5e0819
        }
Packit 5e0819
      fallback_str_start++;
Packit 5e0819
Packit 5e0819
      end = strrchr (str, ')');
Packit 5e0819
Packit 5e0819
      if (color_name_start == NULL || fallback_str_start == NULL || end == NULL)
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Gtk:custom format is 'gtk:custom(color_name,fallback)', '%s' does not fit the format"),
Packit 5e0819
                       str);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      fallback_str = g_strndup (fallback_str_start, end - fallback_str_start);
Packit 5e0819
      fallback = meta_color_spec_new_from_string (fallback_str, error);
Packit 5e0819
      g_free (fallback_str);
Packit 5e0819
Packit 5e0819
      if (fallback == NULL)
Packit 5e0819
        return NULL;
Packit 5e0819
Packit 5e0819
      color_name = g_strndup (color_name_start, fallback_str_start - color_name_start - 1);
Packit 5e0819
Packit 5e0819
      spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM);
Packit 5e0819
      spec->data.gtkcustom.color_name = color_name;
Packit 5e0819
      spec->data.gtkcustom.fallback = fallback;
Packit 5e0819
    }
Packit 5e0819
  else if (strncmp (str, "gtk:", 4) == 0)
Packit 5e0819
    {
Packit 5e0819
      const gchar *bracket;
Packit 5e0819
      const gchar *end_bracket;
Packit 5e0819
      gchar *tmp;
Packit 5e0819
      GtkStateFlags state;
Packit 5e0819
      MetaGtkColorComponent component;
Packit 5e0819
Packit 5e0819
      bracket = str;
Packit 5e0819
      while (*bracket && *bracket != '[')
Packit 5e0819
        ++bracket;
Packit 5e0819
Packit 5e0819
      if (*bracket == '\0')
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse '%s'"),
Packit 5e0819
                       str);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      end_bracket = bracket;
Packit 5e0819
      ++end_bracket;
Packit 5e0819
      while (*end_bracket && *end_bracket != ']')
Packit 5e0819
        ++end_bracket;
Packit 5e0819
Packit 5e0819
      if (*end_bracket == '\0')
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("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'"),
Packit 5e0819
                       str);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
Packit 5e0819
      if (!meta_gtk_state_from_string (tmp, &state))
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Did not understand state '%s' in color specification"),
Packit 5e0819
                       tmp);
Packit 5e0819
          g_free (tmp);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
      g_free (tmp);
Packit 5e0819
Packit 5e0819
      tmp = g_strndup (str + 4, bracket - str - 4);
Packit 5e0819
      component = meta_color_component_from_string (tmp);
Packit 5e0819
      if (component == META_GTK_COLOR_LAST)
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Did not understand color component '%s' in color specification"),
Packit 5e0819
                       tmp);
Packit 5e0819
          g_free (tmp);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
      g_free (tmp);
Packit 5e0819
Packit 5e0819
      spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
Packit 5e0819
      spec->data.gtk.state = state;
Packit 5e0819
      spec->data.gtk.component = component;
Packit 5e0819
      g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
Packit 5e0819
    }
Packit 5e0819
  else if (strncmp (str, "blend/", 6) == 0)
Packit 5e0819
    {
Packit 5e0819
      gchar **split;
Packit 5e0819
      gdouble alpha;
Packit 5e0819
      gchar *end;
Packit 5e0819
      MetaColorSpec *fg;
Packit 5e0819
      MetaColorSpec *bg;
Packit 5e0819
Packit 5e0819
      split = g_strsplit (str, "/", 4);
Packit 5e0819
Packit 5e0819
      if (split[0] == NULL || split[1] == NULL ||
Packit 5e0819
          split[2] == NULL || split[3] == NULL)
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Blend format is 'blend/bg_color/fg_color/alpha', '%s' does not fit the format"),
Packit 5e0819
                       str);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      alpha = g_ascii_strtod (split[3], &end;;
Packit 5e0819
      if (end == split[3])
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Could not parse alpha value '%s' in blended color"),
Packit 5e0819
                       split[3]);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Alpha value '%s' in blended color is not between 0.0 and 1.0"),
Packit 5e0819
                       split[3]);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      fg = NULL;
Packit 5e0819
      bg = NULL;
Packit 5e0819
Packit 5e0819
      bg = meta_color_spec_new_from_string (split[1], error);
Packit 5e0819
      if (bg == NULL)
Packit 5e0819
        {
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      fg = meta_color_spec_new_from_string (split[2], error);
Packit 5e0819
      if (fg == NULL)
Packit 5e0819
        {
Packit 5e0819
          meta_color_spec_free (bg);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      g_strfreev (split);
Packit 5e0819
Packit 5e0819
      spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
Packit 5e0819
      spec->data.blend.alpha = alpha;
Packit 5e0819
      spec->data.blend.background = bg;
Packit 5e0819
      spec->data.blend.foreground = fg;
Packit 5e0819
    }
Packit 5e0819
  else if (strncmp (str, "shade/", 6) == 0)
Packit 5e0819
    {
Packit 5e0819
      gchar **split;
Packit 5e0819
      gdouble factor;
Packit 5e0819
      gchar *end;
Packit 5e0819
      MetaColorSpec *base;
Packit 5e0819
Packit 5e0819
      split = g_strsplit (str, "/", 3);
Packit 5e0819
Packit 5e0819
      if (split[0] == NULL || split[1] == NULL || split[2] == NULL)
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Shade format is 'shade/base_color/factor', '%s' does not fit the format"),
Packit 5e0819
                       str);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      factor = g_ascii_strtod (split[2], &end;;
Packit 5e0819
      if (end == split[2])
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Could not parse shade factor '%s' in shaded color"),
Packit 5e0819
                       split[2]);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      if (factor < (0.0 - 1e6))
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Shade factor '%s' in shaded color is negative"),
Packit 5e0819
                       split[2]);
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      base = meta_color_spec_new_from_string (split[1], error);
Packit 5e0819
      if (base == NULL)
Packit 5e0819
        {
Packit 5e0819
          g_strfreev (split);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
Packit 5e0819
      g_strfreev (split);
Packit 5e0819
Packit 5e0819
      spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
Packit 5e0819
      spec->data.shade.factor = factor;
Packit 5e0819
      spec->data.shade.base = base;
Packit 5e0819
    }
Packit 5e0819
  else
Packit 5e0819
    {
Packit 5e0819
      spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
Packit 5e0819
Packit 5e0819
      if (!gdk_rgba_parse (&spec->data.basic.color, str))
Packit 5e0819
        {
Packit 5e0819
          g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
Packit 5e0819
                       _("Could not parse color '%s'"), str);
Packit 5e0819
          meta_color_spec_free (spec);
Packit 5e0819
          return NULL;
Packit 5e0819
        }
Packit 5e0819
    }
Packit 5e0819
Packit 5e0819
  g_assert (spec);
Packit 5e0819
Packit 5e0819
  return spec;
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
MetaColorSpec *
Packit 5e0819
meta_color_spec_new_gtk (MetaGtkColorComponent component,
Packit 5e0819
                         GtkStateFlags         state)
Packit 5e0819
{
Packit 5e0819
  MetaColorSpec *spec;
Packit 5e0819
Packit 5e0819
  spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
Packit 5e0819
Packit 5e0819
  spec->data.gtk.component = component;
Packit 5e0819
  spec->data.gtk.state = state;
Packit 5e0819
Packit 5e0819
  return spec;
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
void
Packit 5e0819
meta_color_spec_free (MetaColorSpec *spec)
Packit 5e0819
{
Packit 5e0819
  g_return_if_fail (spec != NULL);
Packit 5e0819
Packit 5e0819
  switch (spec->type)
Packit 5e0819
    {
Packit 5e0819
      case META_COLOR_SPEC_BASIC:
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK:
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK_CUSTOM:
Packit 5e0819
        if (spec->data.gtkcustom.color_name)
Packit 5e0819
          g_free (spec->data.gtkcustom.color_name);
Packit 5e0819
        if (spec->data.gtkcustom.fallback)
Packit 5e0819
          meta_color_spec_free (spec->data.gtkcustom.fallback);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_BLEND:
Packit 5e0819
        if (spec->data.blend.foreground)
Packit 5e0819
          meta_color_spec_free (spec->data.blend.foreground);
Packit 5e0819
        if (spec->data.blend.background)
Packit 5e0819
          meta_color_spec_free (spec->data.blend.background);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_SHADE:
Packit 5e0819
        if (spec->data.shade.base)
Packit 5e0819
          meta_color_spec_free (spec->data.shade.base);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      default:
Packit 5e0819
        break;
Packit 5e0819
    }
Packit 5e0819
Packit 5e0819
  g_free (spec);
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
void
Packit 5e0819
meta_color_spec_render (MetaColorSpec   *spec,
Packit 5e0819
                        GtkStyleContext *context,
Packit 5e0819
                        GdkRGBA         *color)
Packit 5e0819
{
Packit 5e0819
  g_return_if_fail (spec != NULL);
Packit 5e0819
  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
Packit 5e0819
Packit 5e0819
  switch (spec->type)
Packit 5e0819
    {
Packit 5e0819
      case META_COLOR_SPEC_BASIC:
Packit 5e0819
        *color = spec->data.basic.color;
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK:
Packit 5e0819
        set_color_from_style (color, context, spec->data.gtk.state,
Packit 5e0819
                              spec->data.gtk.component);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_GTK_CUSTOM:
Packit 5e0819
        set_custom_color_from_style (color, context,
Packit 5e0819
                                     spec->data.gtkcustom.color_name,
Packit 5e0819
                                     spec->data.gtkcustom.fallback);
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_BLEND:
Packit 5e0819
        {
Packit 5e0819
          GdkRGBA bg;
Packit 5e0819
          GdkRGBA fg;
Packit 5e0819
Packit 5e0819
          meta_color_spec_render (spec->data.blend.background, context, &bg;;
Packit 5e0819
          meta_color_spec_render (spec->data.blend.foreground, context, &fg;;
Packit 5e0819
Packit 5e0819
          color_composite (&bg, &fg, spec->data.blend.alpha,
Packit 5e0819
                           &spec->data.blend.color);
Packit 5e0819
Packit 5e0819
          *color = spec->data.blend.color;
Packit 5e0819
        }
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      case META_COLOR_SPEC_SHADE:
Packit 5e0819
        {
Packit 5e0819
          meta_color_spec_render (spec->data.shade.base, context,
Packit 5e0819
                                  &spec->data.shade.color);
Packit 5e0819
Packit 5e0819
          meta_color_shade (&spec->data.shade.color, spec->data.shade.factor,
Packit 5e0819
                            &spec->data.shade.color);
Packit 5e0819
Packit 5e0819
          *color = spec->data.shade.color;
Packit 5e0819
        }
Packit 5e0819
        break;
Packit 5e0819
Packit 5e0819
      default:
Packit 5e0819
        break;
Packit 5e0819
    }
Packit 5e0819
}
Packit 5e0819
Packit 5e0819
/**
Packit 5e0819
 * meta_gtk_state_from_string:
Packit 5e0819
 * @str: state string
Packit 5e0819
 * @state: (out): location to store #GtkStateFlags
Packit 5e0819
 *
Packit 5e0819
 * Convert string to #GtkStateFlags
Packit 5e0819
 *
Packit 5e0819
 * Returns: %TRUE if state string was valid, %FALSE otherwise
Packit 5e0819
 */
Packit 5e0819
gboolean
Packit 5e0819
meta_gtk_state_from_string (const gchar   *str,
Packit 5e0819
                            GtkStateFlags *state)
Packit 5e0819
{
Packit 5e0819
  if (g_ascii_strcasecmp ("normal", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_NORMAL;
Packit 5e0819
  else if (g_ascii_strcasecmp ("prelight", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_PRELIGHT;
Packit 5e0819
  else if (g_ascii_strcasecmp ("active", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_ACTIVE;
Packit 5e0819
  else if (g_ascii_strcasecmp ("selected", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_SELECTED;
Packit 5e0819
  else if (g_ascii_strcasecmp ("insensitive", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_INSENSITIVE;
Packit 5e0819
  else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_INCONSISTENT;
Packit 5e0819
  else if (g_ascii_strcasecmp ("focused", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_FOCUSED;
Packit 5e0819
  else if (g_ascii_strcasecmp ("backdrop", str) == 0)
Packit 5e0819
    *state = GTK_STATE_FLAG_BACKDROP;
Packit 5e0819
  else
Packit 5e0819
    return FALSE;
Packit 5e0819
Packit 5e0819
  return TRUE;
Packit 5e0819
}