[gtk+/wip/css: 11/97] css: Redo StyleProvider interface



commit 8ed2e0764af6121f15cf9db575f641a55995f03e
Author: Benjamin Otte <otte redhat com>
Date:   Wed Dec 28 22:59:55 2011 +0100

    css: Redo StyleProvider interface
    
    We now use the GtkStleProviderPrivate interface, which hopefully is
    faster and more conformant to CSS. Long term, it definitely should be
    both.
    
    I would have liked to split this up into multiple commits, but couldn't
    find a way.

 gtk/Makefile.am                 |    4 +
 gtk/gtkcsslookup.c              |  107 ++++++++++++++++++++++++++++
 gtk/gtkcsslookupprivate.h       |   46 ++++++++++++
 gtk/gtkcssprovider.c            |   80 +++++++++++++++++++++-
 gtk/gtkmodifierstyle.c          |   40 ++++++++++-
 gtk/gtksettings.c               |   40 ++++++++++-
 gtk/gtkstylecontext.c           |  147 +++++++++++++++++++++++++++++----------
 gtk/gtkstyleproperties.c        |   63 ++++++++++++++++-
 gtk/gtkstylepropertiesprivate.h |    1 +
 gtk/gtkstyleproperty.c          |   26 ++++++-
 gtk/gtkstylepropertyprivate.h   |    1 +
 gtk/gtkstyleproviderprivate.c   |   66 +++++++++++++++++
 gtk/gtkstyleproviderprivate.h   |   62 ++++++++++++++++
 13 files changed, 634 insertions(+), 49 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 29ddcf4..bdd05dc 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -409,6 +409,7 @@ gtk_private_h_sources =		\
 	gtkbuttonprivate.h	\
 	gtkcellareaboxcontextprivate.h	\
 	gtkcontainerprivate.h   \
+	gtkcsslookupprivate.h	\
 	gtkcssparserprivate.h	\
 	gtkcssproviderprivate.h	\
 	gtkcsssectionprivate.h 	\
@@ -466,6 +467,7 @@ gtk_private_h_sources =		\
 	gtkstylecontextprivate.h \
 	gtkstylepropertiesprivate.h \
 	gtkstylepropertyprivate.h \
+	gtkstyleproviderprivate.h \
 	gtksymboliccolorprivate.h \
 	gtktextbtree.h		\
 	gtktextbufferserialize.h \
@@ -578,6 +580,7 @@ gtk_base_c_sources = 		\
 	gtkcombobox.c		\
 	gtkcomboboxtext.c	\
 	gtkcontainer.c		\
+	gtkcsslookup.c		\
 	gtkcssparser.c		\
 	gtkcssprovider.c	\
 	gtkcsssection.c 	\
@@ -704,6 +707,7 @@ gtk_base_c_sources = 		\
 	gtkstyleproperties.c	\
 	gtkstyleproperty.c	\
 	gtkstyleprovider.c	\
+	gtkstyleproviderprivate.c	\
 	gtkswitch.c		\
 	gtksymboliccolor.c	\
 	gtktestutils.c		\
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
new file mode 100644
index 0000000..a1e4247
--- /dev/null
+++ b/gtk/gtkcsslookup.c
@@ -0,0 +1,107 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtkcsslookupprivate.h"
+
+#include "gtkstylepropertyprivate.h"
+#include "gtkstylepropertiesprivate.h"
+
+struct _GtkCssLookup {
+  GtkBitmask    *missing;
+  const GValue  *values[1];
+};
+
+GtkCssLookup *
+_gtk_css_lookup_new (void)
+{
+  GtkCssLookup *lookup;
+  guint n = _gtk_style_property_get_count ();
+
+  lookup = g_malloc0 (sizeof (GtkCssLookup) + sizeof (const GValue *) * n);
+  lookup->missing = _gtk_bitmask_new ();
+  _gtk_bitmask_invert_range (lookup->missing, 0, n);
+
+  return lookup;
+}
+
+void
+_gtk_css_lookup_free (GtkCssLookup *lookup)
+{
+  g_return_if_fail (lookup != NULL);
+
+  _gtk_bitmask_free (lookup->missing);
+  g_free (lookup);
+}
+
+const GtkBitmask *
+_gtk_css_lookup_get_missing (const GtkCssLookup *lookup)
+{
+  g_return_val_if_fail (lookup != NULL, NULL);
+
+  return lookup->missing;
+}
+
+gboolean
+_gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
+                            guint               id)
+{
+  g_return_val_if_fail (lookup != NULL, FALSE);
+
+  return lookup->values[id] == NULL;
+}
+
+void
+_gtk_css_lookup_set (GtkCssLookup *lookup,
+                     guint         id,
+                     const GValue *value)
+{
+  g_return_if_fail (lookup != NULL);
+  g_return_if_fail (_gtk_bitmask_get (lookup->missing, id));
+  g_return_if_fail (value != NULL);
+
+  _gtk_bitmask_set (lookup->missing, id, FALSE);
+  lookup->values[id] = value;
+}
+
+GtkStyleProperties *
+_gtk_css_lookup_resolve (GtkCssLookup *lookup)
+{
+  GtkStyleProperties *props;
+  guint i, n;
+
+  g_return_val_if_fail (lookup != NULL, NULL);
+
+  n = _gtk_style_property_get_count ();
+  props = gtk_style_properties_new ();
+
+  for (i = 0; i < n; i++)
+    {
+      if (lookup->values[i] == NULL)
+        continue;
+
+      _gtk_style_properties_set_property_by_property (props,
+                                                      _gtk_style_property_get (i),
+                                                      0,
+                                                      lookup->values[i]);
+    }
+
+  return props;
+}
diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h
new file mode 100644
index 0000000..b1d6d5e
--- /dev/null
+++ b/gtk/gtkcsslookupprivate.h
@@ -0,0 +1,46 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_CSS_LOOKUP_PRIVATE_H__
+#define __GTK_CSS_LOOKUP_PRIVATE_H__
+
+#include <glib-object.h>
+#include "gtk/gtkbitmaskprivate.h"
+#include "gtk/gtkstyleproperties.h"
+
+
+G_BEGIN_DECLS
+
+typedef struct _GtkCssLookup GtkCssLookup;
+
+GtkCssLookup *          _gtk_css_lookup_new                     (void);
+void                    _gtk_css_lookup_free                    (GtkCssLookup       *lookup);
+
+const GtkBitmask *      _gtk_css_lookup_get_missing             (const GtkCssLookup *lookup);
+gboolean                _gtk_css_lookup_is_missing              (const GtkCssLookup *lookup,
+                                                                 guint               id);
+void                    _gtk_css_lookup_set                     (GtkCssLookup       *lookup,
+                                                                 guint               id,
+                                                                 const GValue       *value);
+GtkStyleProperties *    _gtk_css_lookup_resolve                 (GtkCssLookup       *lookup);
+
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_LOOKUP_PRIVATE_H__ */
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 81655bd..6926192 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -36,6 +36,7 @@
 #include "gtkstylecontextprivate.h"
 #include "gtkstylepropertiesprivate.h"
 #include "gtkstylepropertyprivate.h"
+#include "gtkstyleproviderprivate.h"
 #include "gtkbindings.h"
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
@@ -995,6 +996,7 @@ static guint css_provider_signals[LAST_SIGNAL] = { 0 };
 
 static void gtk_css_provider_finalize (GObject *object);
 static void gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface);
+static void gtk_css_style_provider_private_iface_init (GtkStyleProviderPrivateInterface *iface);
 
 static gboolean
 gtk_css_provider_load_internal (GtkCssProvider *css_provider,
@@ -1011,7 +1013,9 @@ gtk_css_provider_error_quark (void)
 
 G_DEFINE_TYPE_EXTENDED (GtkCssProvider, gtk_css_provider, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
-                                               gtk_css_style_provider_iface_init));
+                                               gtk_css_style_provider_iface_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
+                                               gtk_css_style_provider_private_iface_init));
 
 static void
 gtk_css_provider_parsing_error (GtkCssProvider  *provider,
@@ -1515,6 +1519,80 @@ gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface)
   iface->get_style_property = gtk_css_provider_get_style_property;
 }
 
+static GtkSymbolicColor *
+gtk_css_style_provider_get_color (GtkStyleProviderPrivate *provider,
+                                  const char              *name)
+{
+  GtkCssProvider *css_provider = GTK_CSS_PROVIDER (provider);
+
+  return g_hash_table_lookup (css_provider->priv->symbolic_colors, name);
+}
+
+static void
+gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
+                               GtkWidgetPath           *path,
+                               GtkStateFlags            state,
+                               GtkCssLookup            *lookup)
+{
+  GtkCssProvider *css_provider;
+  GtkCssProviderPrivate *priv;
+  guint l, length;
+  int i;
+
+  css_provider = GTK_CSS_PROVIDER (provider);
+  priv = css_provider->priv;
+  length = gtk_widget_path_length (path);
+
+  for (l = length; l > 0; l--)
+    {
+      for (i = priv->rulesets->len - 1; i >= 0; i--)
+        {
+          GtkCssRuleset *ruleset;
+          GHashTableIter iter;
+          gpointer key, val;
+          GtkStateFlags selector_state;
+
+          ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
+
+          if (ruleset->style == NULL)
+            continue;
+
+          selector_state = _gtk_css_selector_get_state_flags (ruleset->selector);
+          if (l < length && (!ruleset->has_inherit || selector_state))
+            continue;
+
+          if ((selector_state & state) != selector_state)
+            continue;
+
+          if (!gtk_css_ruleset_matches (ruleset, path, l))
+            continue;
+
+          g_hash_table_iter_init (&iter, ruleset->style);
+
+          while (g_hash_table_iter_next (&iter, &key, &val))
+            {
+              GtkStyleProperty *prop = key;
+              PropertyValue *value = val;
+
+              if (l != length && !_gtk_style_property_is_inherit (prop))
+                continue;
+
+              if (!_gtk_css_lookup_is_missing (lookup, _gtk_style_property_get_id (prop)))
+                continue;
+
+              _gtk_css_lookup_set (lookup, _gtk_style_property_get_id (prop), &value->value);
+            }
+        }
+    }
+}
+
+static void
+gtk_css_style_provider_private_iface_init (GtkStyleProviderPrivateInterface *iface)
+{
+  iface->get_color = gtk_css_style_provider_get_color;
+  iface->lookup = gtk_css_style_provider_lookup;
+}
+
 static void
 gtk_css_provider_finalize (GObject *object)
 {
diff --git a/gtk/gtkmodifierstyle.c b/gtk/gtkmodifierstyle.c
index d81b9bc..efb1008 100644
--- a/gtk/gtkmodifierstyle.c
+++ b/gtk/gtkmodifierstyle.c
@@ -19,6 +19,7 @@
 
 #include "config.h"
 #include "gtkmodifierstyle.h"
+#include "gtkstyleproviderprivate.h"
 #include "gtkintl.h"
 
 typedef struct StylePropertyValue StylePropertyValue;
@@ -36,12 +37,15 @@ enum {
 
 static guint signals [LAST_SIGNAL] = { 0 };
 
-static void gtk_modifier_style_provider_init (GtkStyleProviderIface *iface);
-static void gtk_modifier_style_finalize      (GObject      *object);
+static void gtk_modifier_style_provider_init         (GtkStyleProviderIface            *iface);
+static void gtk_modifier_style_provider_private_init (GtkStyleProviderPrivateInterface *iface);
+static void gtk_modifier_style_finalize              (GObject                          *object);
 
 G_DEFINE_TYPE_EXTENDED (GtkModifierStyle, _gtk_modifier_style, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
-                                               gtk_modifier_style_provider_init));
+                                               gtk_modifier_style_provider_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
+                                               gtk_modifier_style_provider_private_init));
 
 static void
 _gtk_modifier_style_class_init (GtkModifierStyleClass *klass)
@@ -131,6 +135,36 @@ gtk_modifier_style_provider_init (GtkStyleProviderIface *iface)
   iface->get_style_property = gtk_modifier_style_get_style_property;
 }
 
+static GtkSymbolicColor *
+gtk_modifier_style_provider_get_color (GtkStyleProviderPrivate *provider,
+                                       const char              *name)
+{
+  GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider);
+
+  return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style), name);
+}
+
+static void
+gtk_modifier_style_provider_lookup (GtkStyleProviderPrivate *provider,
+                                    GtkWidgetPath           *path,
+                                    GtkStateFlags            state,
+                                    GtkCssLookup            *lookup)
+{
+  GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider);
+
+  _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style),
+                                      path,
+                                      state,
+                                      lookup);
+}
+
+static void
+gtk_modifier_style_provider_private_init (GtkStyleProviderPrivateInterface *iface)
+{
+  iface->get_color = gtk_modifier_style_provider_get_color;
+  iface->lookup = gtk_modifier_style_provider_lookup;
+}
+
 static void
 gtk_modifier_style_finalize (GObject *object)
 {
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index 508b4db..ac90cdd 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -32,6 +32,7 @@
 #include "gtkwidget.h"
 #include "gtkprivate.h"
 #include "gtkcssproviderprivate.h"
+#include "gtkstyleproviderprivate.h"
 #include "gtksymboliccolor.h"
 #include "gtktypebuiltins.h"
 #include "gtkversion.h"
@@ -211,6 +212,7 @@ enum {
 
 /* --- prototypes --- */
 static void     gtk_settings_provider_iface_init (GtkStyleProviderIface *iface);
+static void     gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface);
 
 static void     gtk_settings_finalize            (GObject               *object);
 static void     gtk_settings_get_property        (GObject               *object,
@@ -259,7 +261,9 @@ static guint             class_n_properties = 0;
 
 G_DEFINE_TYPE_EXTENDED (GtkSettings, gtk_settings, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
-                                               gtk_settings_provider_iface_init));
+                                               gtk_settings_provider_iface_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
+                                               gtk_settings_provider_private_init));
 
 /* --- functions --- */
 static void
@@ -1450,6 +1454,40 @@ gtk_settings_provider_iface_init (GtkStyleProviderIface *iface)
   iface->get_style = gtk_settings_get_style;
 }
 
+static GtkSymbolicColor *
+gtk_settings_style_provider_get_color (GtkStyleProviderPrivate *provider,
+                                       const char              *name)
+{
+  GtkSettings *settings = GTK_SETTINGS (provider);
+
+  settings_ensure_style (settings);
+
+  return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style), name);
+}
+
+static void
+gtk_settings_style_provider_lookup (GtkStyleProviderPrivate *provider,
+                                    GtkWidgetPath           *path,
+                                    GtkStateFlags            state,
+                                    GtkCssLookup            *lookup)
+{
+  GtkSettings *settings = GTK_SETTINGS (provider);
+
+  settings_ensure_style (settings);
+
+  _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style),
+                                      path,
+                                      state,
+                                      lookup);
+}
+
+static void
+gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface)
+{
+  iface->get_color = gtk_settings_style_provider_get_color;
+  iface->lookup = gtk_settings_style_provider_lookup;
+}
+
 static void
 gtk_settings_finalize (GObject *object)
 {
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 934c635..21516d3 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -32,11 +32,12 @@
 #include "gtkwidget.h"
 #include "gtkwindow.h"
 #include "gtkprivate.h"
-#include "gtksymboliccolor.h"
+#include "gtksymboliccolorprivate.h"
 #include "gtkanimationdescription.h"
 #include "gtktimeline.h"
 #include "gtkiconfactory.h"
 #include "gtkwidgetprivate.h"
+#include "gtkstyleproviderprivate.h"
 
 /**
  * SECTION:gtkstylecontext
@@ -371,6 +372,7 @@ struct _GtkStyleContextPrivate
   GHashTable *style_data;
   GSList *info_stack;
   StyleData *current_data;
+  GtkStateFlags current_state;
 
   GSList *animation_regions;
   GSList *animations;
@@ -408,6 +410,9 @@ static void gtk_style_context_impl_get_property (GObject      *object,
                                                  guint         prop_id,
                                                  GValue       *value,
                                                  GParamSpec   *pspec);
+static GtkSymbolicColor *
+            gtk_style_context_color_lookup_func (gpointer      contextp,
+                                                 const char   *name);
 
 
 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
@@ -556,7 +561,6 @@ style_data_new (void)
   StyleData *data;
 
   data = g_slice_new0 (StyleData);
-  data->store = gtk_style_properties_new ();
 
   return data;
 }
@@ -908,18 +912,25 @@ find_next_candidate (GList    *local,
 static void
 build_properties (GtkStyleContext *context,
                   StyleData       *style_data,
-                  GtkWidgetPath   *path)
+                  GtkWidgetPath   *path,
+                  GtkStateFlags    state)
 {
   GtkStyleContextPrivate *priv;
   GList *elem, *list, *global_list = NULL;
+  GtkCssLookup *lookup;
 
   priv = context->priv;
-  list = priv->providers;
+  list = priv->providers_last;
 
   if (priv->screen)
-    global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
+    {
+      global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
+      global_list = g_list_last (global_list);
+    }
+
+  lookup = _gtk_css_lookup_new ();
 
-  while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL)
+  while ((elem = find_next_candidate (list, global_list, FALSE)) != NULL)
     {
       GtkStyleProviderData *data;
       GtkStyleProperties *provider_style;
@@ -927,18 +938,37 @@ build_properties (GtkStyleContext *context,
       data = elem->data;
 
       if (elem == list)
-        list = list->next;
+        list = list->prev;
       else
-        global_list = global_list->next;
-
-      provider_style = gtk_style_provider_get_style (data->provider, path);
+        global_list = global_list->prev;
 
-      if (provider_style)
+      if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider))
         {
-          gtk_style_properties_merge (style_data->store, provider_style, TRUE);
-          g_object_unref (provider_style);
+          _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (data->provider),
+                                              path,
+                                              state,
+                                              lookup);
+        }
+      else
+        {
+          provider_style = gtk_style_provider_get_style (data->provider, path);
+
+          if (provider_style)
+            {
+              _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (provider_style),
+                                                  path,
+                                                  state,
+                                                  lookup);
+              g_object_unref (provider_style);
+            }
         }
     }
+
+  style_data->store = _gtk_css_lookup_resolve (lookup);
+  _gtk_style_properties_set_color_lookup_func (style_data->store,
+                                               gtk_style_context_color_lookup_func,
+                                               context);
+  _gtk_css_lookup_free (lookup);
 }
 
 static void
@@ -1027,7 +1057,7 @@ style_data_lookup (GtkStyleContext *context,
   state_mismatch = ((GtkStyleInfo *) priv->info_stack->data)->state_flags != state;
 
   /* Current data in use is cached, just return it */
-  if (priv->current_data && !state_mismatch)
+  if (priv->current_data && priv->current_state == state)
     return priv->current_data;
 
   g_assert (priv->widget_path != NULL);
@@ -1047,7 +1077,7 @@ style_data_lookup (GtkStyleContext *context,
       data = style_data_new ();
       path = create_query_path (context);
 
-      build_properties (context, data, path);
+      build_properties (context, data, path, state);
       build_icon_factories (context, data, path);
 
       g_hash_table_insert (priv->style_data,
@@ -1060,12 +1090,9 @@ style_data_lookup (GtkStyleContext *context,
   if (G_UNLIKELY (state_mismatch))
     {
       gtk_style_context_restore (context);
-      priv->current_data = NULL;
     }
   else
     {
-      priv->current_data = data;
-
       if (priv->theming_engine)
         g_object_unref (priv->theming_engine);
 
@@ -1077,6 +1104,9 @@ style_data_lookup (GtkStyleContext *context,
         priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
     }
 
+  priv->current_data = data;
+  priv->current_state = state;
+
   return data;
 }
 
@@ -1384,7 +1414,7 @@ gtk_style_context_get_property (GtkStyleContext *context,
   g_return_if_fail (priv->widget_path != NULL);
 
   data = style_data_lookup (context, state);
-  gtk_style_properties_get_property (data->store, property, state, value);
+  gtk_style_properties_get_property (data->store, property, 0, value);
 }
 
 void
@@ -1402,7 +1432,7 @@ _gtk_style_context_get_valist (GtkStyleContext *context,
   g_return_if_fail (priv->widget_path != NULL);
 
   data = style_data_lookup (context, state);
-  _gtk_style_properties_get_valist (data->store, state, property_context, args);
+  _gtk_style_properties_get_valist (data->store, 0, property_context, args);
 }
 
 /**
@@ -1429,7 +1459,7 @@ gtk_style_context_get_valist (GtkStyleContext *context,
   g_return_if_fail (priv->widget_path != NULL);
 
   data = style_data_lookup (context, state);
-  gtk_style_properties_get_valist (data->store, state, args);
+  gtk_style_properties_get_valist (data->store, 0, args);
 }
 
 /**
@@ -1460,7 +1490,7 @@ gtk_style_context_get (GtkStyleContext *context,
   data = style_data_lookup (context, state);
 
   va_start (args, state);
-  gtk_style_properties_get_valist (data->store, state, args);
+  gtk_style_properties_get_valist (data->store, 0, args);
   va_end (args);
 }
 
@@ -2691,6 +2721,51 @@ gtk_style_context_get_junction_sides (GtkStyleContext *context)
   return info->junction_sides;
 }
 
+static GtkSymbolicColor *
+gtk_style_context_color_lookup_func (gpointer    contextp,
+                                     const char *name)
+{
+  GtkSymbolicColor *sym_color;
+  GtkStyleContext *context = contextp;
+  GtkStyleContextPrivate *priv = context->priv;
+  GList *elem, *list, *global_list = NULL;
+
+  list = priv->providers_last;
+  if (priv->screen)
+    {
+      global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
+      global_list = g_list_last (global_list);
+    }
+
+  sym_color = NULL;
+  
+  while (sym_color == NULL &&
+         (elem = find_next_candidate (list, global_list, FALSE)) != NULL)
+    {
+      GtkStyleProviderData *data;
+
+      data = elem->data;
+
+      if (elem == list)
+        list = list->prev;
+      else
+        global_list = global_list->prev;
+
+      if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider))
+        {
+          sym_color = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (data->provider),
+                                                             name);
+        }
+      else
+        {
+          /* If somebody hits this code path, shout at them */
+          sym_color = NULL;
+        }
+    }
+
+  return sym_color;
+}
+
 /**
  * gtk_style_context_lookup_color:
  * @context: a #GtkStyleContext
@@ -2706,24 +2781,20 @@ gtk_style_context_lookup_color (GtkStyleContext *context,
                                 const gchar     *color_name,
                                 GdkRGBA         *color)
 {
-  GtkStyleContextPrivate *priv;
   GtkSymbolicColor *sym_color;
-  StyleData *data;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
   g_return_val_if_fail (color_name != NULL, FALSE);
   g_return_val_if_fail (color != NULL, FALSE);
 
-  priv = context->priv;
-  g_return_val_if_fail (priv->widget_path != NULL, FALSE);
-
-  data = style_data_lookup (context, 0);
-  sym_color = gtk_style_properties_lookup_color (data->store, color_name);
-
-  if (!sym_color)
+  sym_color = gtk_style_context_color_lookup_func (context, color_name);
+  if (sym_color == NULL)
     return FALSE;
 
-  return gtk_symbolic_color_resolve (sym_color, data->store, color);
+  return _gtk_symbolic_color_resolve_full (sym_color,
+                                           gtk_style_context_color_lookup_func,
+                                           context,
+                                           color);
 }
 
 /**
@@ -2830,8 +2901,8 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
   /* Find out if there is any animation description for the given
    * state, it will fallback to the normal state as well if necessary.
    */
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get (data->store, flags,
+  data = style_data_lookup (context, flags);
+  gtk_style_properties_get (data->store, 0,
                             "transition", &desc,
                             NULL);
 
@@ -3377,7 +3448,7 @@ gtk_style_context_get_border (GtkStyleContext *context,
 
   data = style_data_lookup (context, state);
   gtk_style_properties_get (data->store,
-                            state,
+                            0,
 			    "border-style", &border_style,
                             "border-top-width", &top,
                             "border-top-width", &top,
@@ -3429,7 +3500,7 @@ gtk_style_context_get_padding (GtkStyleContext *context,
 
   data = style_data_lookup (context, state);
   gtk_style_properties_get (data->store,
-                            state,
+                            0,
                             "padding-top", &top,
                             "padding-left", &left,
                             "padding-bottom", &bottom,
@@ -3470,7 +3541,7 @@ gtk_style_context_get_margin (GtkStyleContext *context,
 
   data = style_data_lookup (context, state);
   gtk_style_properties_get (data->store,
-                            state,
+                            0,
                             "margin-top", &top,
                             "margin-left", &left,
                             "margin-bottom", &bottom,
@@ -3533,7 +3604,7 @@ gtk_style_context_get_font (GtkStyleContext *context,
 
   if (description == NULL)
     {
-      gtk_style_properties_get (data->store, state, "font", &description, NULL);
+      gtk_style_properties_get (data->store, 0, "font", &description, NULL);
       g_hash_table_insert (font_cache, GUINT_TO_POINTER (state), description);
     }
 
diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c
index 5470bf5..f2b6b7d 100644
--- a/gtk/gtkstyleproperties.c
+++ b/gtk/gtkstyleproperties.c
@@ -35,6 +35,7 @@
 #include "gtkborderimageprivate.h"
 
 #include "gtkstylepropertyprivate.h"
+#include "gtkstyleproviderprivate.h"
 #include "gtkintl.h"
 
 #include "gtkwin32themeprivate.h"
@@ -76,15 +77,20 @@ struct _GtkStylePropertiesPrivate
 {
   GHashTable *color_map;
   GHashTable *properties;
+  GtkSymbolicColorLookupFunc color_lookup_func;
+  gpointer color_lookup_data;
 };
 
-static void gtk_style_properties_provider_init (GtkStyleProviderIface *iface);
-static void gtk_style_properties_finalize      (GObject      *object);
+static void gtk_style_properties_provider_init         (GtkStyleProviderIface            *iface);
+static void gtk_style_properties_provider_private_init (GtkStyleProviderPrivateInterface *iface);
+static void gtk_style_properties_finalize              (GObject                          *object);
 
 
 G_DEFINE_TYPE_EXTENDED (GtkStyleProperties, gtk_style_properties, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
-                                               gtk_style_properties_provider_init));
+                                               gtk_style_properties_provider_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
+                                               gtk_style_properties_provider_private_init));
 
 static void
 gtk_style_properties_class_init (GtkStylePropertiesClass *klass)
@@ -293,6 +299,57 @@ gtk_style_properties_provider_init (GtkStyleProviderIface *iface)
   iface->get_style = gtk_style_properties_get_style;
 }
 
+static GtkSymbolicColor *
+gtk_style_properties_provider_get_color (GtkStyleProviderPrivate *provider,
+                                         const char              *name)
+{
+  return gtk_style_properties_lookup_color (GTK_STYLE_PROPERTIES (provider), name);
+}
+
+static void
+gtk_style_properties_provider_lookup (GtkStyleProviderPrivate *provider,
+                                      GtkWidgetPath           *path,
+                                      GtkStateFlags            state,
+                                      GtkCssLookup            *lookup)
+{
+  GtkStyleProperties *props;
+  GtkStylePropertiesPrivate *priv;
+  GHashTableIter iter;
+  gpointer key, value;
+
+  props = GTK_STYLE_PROPERTIES (provider);
+  priv = props->priv;
+
+  /* Merge symbolic style properties */
+  g_hash_table_iter_init (&iter, priv->properties);
+
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      GtkStyleProperty *prop = key;
+      PropertyData *data = value;
+      const GValue *value;
+      guint id;
+
+      id = _gtk_style_property_get_id (prop);
+
+      if (!_gtk_css_lookup_is_missing (lookup, id))
+          continue;
+
+      value = property_data_match_state (data, state);
+      if (value == NULL)
+        continue;
+
+      _gtk_css_lookup_set (lookup, id, value);
+    }
+}
+
+static void
+gtk_style_properties_provider_private_init (GtkStyleProviderPrivateInterface *iface)
+{
+  iface->get_color = gtk_style_properties_provider_get_color;
+  iface->lookup = gtk_style_properties_provider_lookup;
+}
+
 /* Property registration functions */
 
 /**
diff --git a/gtk/gtkstylepropertiesprivate.h b/gtk/gtkstylepropertiesprivate.h
index 3465270..5da4617 100644
--- a/gtk/gtkstylepropertiesprivate.h
+++ b/gtk/gtkstylepropertiesprivate.h
@@ -23,6 +23,7 @@
 #include "gtkstyleproperties.h"
 #include "gtkstylepropertyprivate.h"
 #include "gtkstylecontextprivate.h"
+#include "gtksymboliccolorprivate.h"
 
 G_BEGIN_DECLS
 
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 681acf6..fee3bba 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -52,7 +52,7 @@
 static GHashTable *parse_funcs = NULL;
 static GHashTable *print_funcs = NULL;
 static GHashTable *properties = NULL;
-static guint __n_style_properties = 0;
+static GPtrArray *__style_property_array = NULL;
 
 static void
 register_conversion_function (GType             type,
@@ -2244,7 +2244,25 @@ border_color_default_value (GtkStyleProperties *props,
 guint
 _gtk_style_property_get_count (void)
 {
-  return __n_style_properties;
+  return __style_property_array ? __style_property_array->len : 0;
+}
+
+const GtkStyleProperty *
+_gtk_style_property_get (guint id)
+{
+  g_assert (__style_property_array);
+  
+  return g_ptr_array_index (__style_property_array, id);
+}
+
+static void
+_gtk_style_property_generate_id (GtkStyleProperty *node)
+{
+  if (__style_property_array == NULL)
+    __style_property_array = g_ptr_array_new ();
+
+  node->id = __style_property_array->len;
+  g_ptr_array_add (__style_property_array, node);
 }
 
 static void
@@ -3145,7 +3163,6 @@ _gtk_style_property_register (GParamSpec               *pspec,
 
   node = g_slice_new0 (GtkStyleProperty);
   node->flags = flags;
-  node->id = __n_style_properties++;
   node->pspec = pspec;
   node->property_parse_func = property_parse_func;
   node->pack_func = pack_func;
@@ -3155,6 +3172,9 @@ _gtk_style_property_register (GParamSpec               *pspec,
   node->default_value_func = default_value_func;
   node->unset_func = unset_func;
 
+  if (!_gtk_style_property_is_shorthand (node))
+    _gtk_style_property_generate_id (node);
+
   /* pspec owns name */
   g_hash_table_insert (properties, (gchar *)pspec->name, node);
 }
diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h
index fc52ae5..6cabf25 100644
--- a/gtk/gtkstylepropertyprivate.h
+++ b/gtk/gtkstylepropertyprivate.h
@@ -64,6 +64,7 @@ struct _GtkStyleProperty
 };
 
 guint                    _gtk_style_property_get_count     (void);
+const GtkStyleProperty * _gtk_style_property_get           (guint                   id);
 
 const GtkStyleProperty * _gtk_style_property_lookup        (const char             *name);
 
diff --git a/gtk/gtkstyleproviderprivate.c b/gtk/gtkstyleproviderprivate.c
new file mode 100644
index 0000000..a7b0a6f
--- /dev/null
+++ b/gtk/gtkstyleproviderprivate.c
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtkstyleproviderprivate.h"
+#include "gtkstyleprovider.h"
+
+G_DEFINE_INTERFACE (GtkStyleProviderPrivate, _gtk_style_provider_private, GTK_TYPE_STYLE_PROVIDER)
+
+static void
+_gtk_style_provider_private_default_init (GtkStyleProviderPrivateInterface *iface)
+{
+}
+
+GtkSymbolicColor *
+_gtk_style_provider_private_get_color (GtkStyleProviderPrivate *provider,
+                                       const char              *name)
+{
+  GtkStyleProviderPrivateInterface *iface;
+
+  g_return_val_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider), NULL);
+
+  iface = GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE (provider);
+
+  if (!iface->get_color)
+    return NULL;
+
+  return iface->get_color (provider, name);
+}
+
+void
+_gtk_style_provider_private_lookup (GtkStyleProviderPrivate *provider,
+                                    GtkWidgetPath           *path,
+                                    GtkStateFlags            state,
+                                    GtkCssLookup            *lookup)
+{
+  GtkStyleProviderPrivateInterface *iface;
+
+  g_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (lookup != NULL);
+
+  iface = GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE (provider);
+
+  if (!iface->lookup)
+    return;
+
+  iface->lookup (provider, path, state, lookup);
+}
diff --git a/gtk/gtkstyleproviderprivate.h b/gtk/gtkstyleproviderprivate.h
new file mode 100644
index 0000000..c2d5421
--- /dev/null
+++ b/gtk/gtkstyleproviderprivate.h
@@ -0,0 +1,62 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_STYLE_PROVIDER_PRIVATE_H__
+#define __GTK_STYLE_PROVIDER_PRIVATE_H__
+
+#include <glib-object.h>
+#include "gtk/gtkcsslookupprivate.h"
+#include <gtk/gtkenums.h>
+#include <gtk/gtksymboliccolor.h>
+#include <gtk/gtkwidgetpath.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_STYLE_PROVIDER_PRIVATE          (_gtk_style_provider_private_get_type ())
+#define GTK_STYLE_PROVIDER_PRIVATE(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE, GtkStyleProviderPrivate))
+#define GTK_IS_STYLE_PROVIDER_PRIVATE(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE))
+#define GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE(o)  (G_TYPE_INSTANCE_GET_INTERFACE ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE, GtkStyleProviderPrivateInterface))
+
+typedef struct _GtkStyleProviderPrivateInterface GtkStyleProviderPrivateInterface;
+typedef struct _GtkStyleProviderPrivate GtkStyleProviderPrivate; /* dummy typedef */
+
+struct _GtkStyleProviderPrivateInterface
+{
+  GTypeInterface g_iface;
+
+  GtkSymbolicColor *    (* get_color)           (GtkStyleProviderPrivate *provider,
+                                                 const char              *name);
+  void                  (* lookup)              (GtkStyleProviderPrivate *provider,
+                                                 GtkWidgetPath           *path,
+                                                 GtkStateFlags            state,
+                                                 GtkCssLookup            *lookup);
+};
+
+GType                   _gtk_style_provider_private_get_type     (void) G_GNUC_CONST;
+
+GtkSymbolicColor *      _gtk_style_provider_private_get_color    (GtkStyleProviderPrivate *provider,
+                                                                  const char              *name);
+void                    _gtk_style_provider_private_lookup       (GtkStyleProviderPrivate *provider,
+                                                                  GtkWidgetPath           *path,
+                                                                  GtkStateFlags            state,
+                                                                  GtkCssLookup            *lookup);
+
+G_END_DECLS
+
+#endif /* __GTK_STYLE_PROVIDER_PRIVATE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]