[gtk+] cssprovider: Redo styles as an array



commit 46082783283a4ceed157d62deaa27d291490f3ba
Author: Benjamin Otte <otte redhat com>
Date:   Thu Mar 1 06:40:15 2012 +0100

    cssprovider: Redo styles as an array
    
    Saves even more memory and avoids an extra copy during assigning.

 gtk/gtkcssprovider.c |  224 +++++++++++++++++++++-----------------------------
 1 files changed, 95 insertions(+), 129 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 39e2620..739b93c 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -967,13 +967,28 @@ typedef struct _WidgetPropertyValue WidgetPropertyValue;
 typedef enum ParserScope ParserScope;
 typedef enum ParserSymbol ParserSymbol;
 
+struct _PropertyValue {
+  GtkCssStyleProperty *property;
+  GValue               value;
+  GtkCssSection       *section;
+};
+
+struct _WidgetPropertyValue {
+  char *name;
+  WidgetPropertyValue *next;
+  GValue         value;
+
+  GtkCssSection *section;
+};
+
 struct GtkCssRuleset
 {
   GtkCssSelector *selector;
   WidgetPropertyValue *widget_style;
-  PropertyValue *style;
+  PropertyValue *styles;
   GtkBitmask *set_styles;
-  guint owns_style : 1;
+  guint n_styles;
+  guint owns_styles : 1;
   guint owns_widget_style : 1;
 };
 
@@ -1008,7 +1023,6 @@ 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 void property_value_list_free (PropertyValue *head);
 static void widget_property_value_list_free (WidgetPropertyValue *head);
 
 static gboolean
@@ -1125,8 +1139,8 @@ gtk_css_ruleset_init_copy (GtkCssRuleset       *new,
 
   new->selector = selector;
   /* First copy takes over ownership */
-  if (ruleset->owns_style)
-    ruleset->owns_style = FALSE;
+  if (ruleset->owns_styles)
+    ruleset->owns_styles = FALSE;
   if (ruleset->owns_widget_style)
     ruleset->owns_widget_style = FALSE;
   if (new->set_styles)
@@ -1136,8 +1150,17 @@ gtk_css_ruleset_init_copy (GtkCssRuleset       *new,
 static void
 gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
 {
-  if (ruleset->owns_style)
-    property_value_list_free (ruleset->style);
+  if (ruleset->owns_styles)
+    {
+      guint i;
+
+      for (i = 0; i < ruleset->n_styles; i++)
+        {
+          g_value_unset (&ruleset->styles[i].value);
+          gtk_css_section_unref (ruleset->styles[i].section);
+        }
+      g_free (ruleset->styles);
+    }
   if (ruleset->set_styles)
     _gtk_bitmask_free (ruleset->set_styles);
   if (ruleset->owns_widget_style)
@@ -1148,79 +1171,6 @@ gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
   memset (ruleset, 0, sizeof (GtkCssRuleset));
 }
 
-struct _PropertyValue {
-  GtkCssStyleProperty *property;
-  PropertyValue       *next;
-  GValue               value;
-  GtkCssSection       *section;
-};
-
-static PropertyValue *
-property_value_new (GtkCssStyleProperty *property, GtkCssSection *section)
-{
-  PropertyValue *value;
-
-  value = g_slice_new0 (PropertyValue);
-
-  value->property = property;
-  value->section = gtk_css_section_ref (section);
-
-  return value;
-}
-
-static void
-property_value_free (PropertyValue *value)
-{
-  if (G_IS_VALUE (&value->value))
-    g_value_unset (&value->value);
-
-  gtk_css_section_unref (value->section);
-
-  g_slice_free (PropertyValue, value);
-}
-
-static void
-property_value_list_free (PropertyValue *head)
-{
-  PropertyValue *l, *next;
-  for (l = head; l != NULL; l = next)
-    {
-      next = l->next;
-      property_value_free (l);
-    }
-}
-
-static PropertyValue *
-property_value_list_remove_property (PropertyValue       *head,
-                                     GtkCssStyleProperty *property)
-{
-  PropertyValue *l, **last;
-
-  last = &head;
-
-  for (l = head; l != NULL; l = l->next)
-    {
-      if (l->property == property)
-	{
-	  *last = l->next;
-	  property_value_free (l);
-	  break;
-	}
-
-      last = &l->next;
-    }
-
-  return head;
-}
-
-struct _WidgetPropertyValue {
-  char *name;
-  WidgetPropertyValue *next;
-  GValue         value;
-
-  GtkCssSection *section;
-};
-
 static WidgetPropertyValue *
 widget_property_value_new (char *name, GtkCssSection *section)
 {
@@ -1291,22 +1241,44 @@ gtk_css_ruleset_add_style (GtkCssRuleset *ruleset,
 
 static void
 gtk_css_ruleset_add (GtkCssRuleset       *ruleset,
-                     GtkCssStyleProperty *prop,
-                     PropertyValue       *value)
+                     GtkCssStyleProperty *property,
+                     const GValue        *value,
+                     GtkCssSection       *section)
 {
-  g_return_if_fail (_gtk_css_style_property_is_specified_type (GTK_CSS_STYLE_PROPERTY (prop),
-                                                               G_VALUE_TYPE (&value->value)));
+  guint i;
+
+  g_return_if_fail (_gtk_css_style_property_is_specified_type (property, G_VALUE_TYPE (value)));
+  g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0);
 
   if (ruleset->set_styles == NULL)
     ruleset->set_styles = _gtk_bitmask_new ();
 
   _gtk_bitmask_set (ruleset->set_styles,
-                    _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (prop)),
+                    _gtk_css_style_property_get_id (property),
                     TRUE);
 
-  value->next = property_value_list_remove_property (ruleset->style, prop);
-  ruleset->style = value;
-  ruleset->owns_style = TRUE;
+  ruleset->owns_styles = TRUE;
+
+  for (i = 0; i < ruleset->n_styles; i++)
+    {
+      if (ruleset->styles[i].property == property)
+        {
+          g_value_unset (&ruleset->styles[i].value);
+          gtk_css_section_unref (ruleset->styles[i].section);
+          break;
+        }
+    }
+  if (i == ruleset->n_styles)
+    {
+      ruleset->n_styles++;
+      ruleset->styles = g_realloc (ruleset->styles, ruleset->n_styles * sizeof (PropertyValue));
+      memset (&ruleset->styles[i].value, 0, sizeof (GValue));
+      ruleset->styles[i].property = property;
+    }
+
+  g_value_init (&ruleset->styles[i].value, G_VALUE_TYPE (value));
+  g_value_copy (value, &ruleset->styles[i].value);
+  ruleset->styles[i].section = gtk_css_section_ref (section);
 }
 
 static gboolean
@@ -1489,7 +1461,7 @@ gtk_css_provider_get_style (GtkStyleProvider *provider,
   GtkCssProvider *css_provider;
   GtkCssProviderPrivate *priv;
   GtkStyleProperties *props;
-  guint i;
+  guint i, j;
 
   css_provider = GTK_CSS_PROVIDER (provider);
   priv = css_provider->priv;
@@ -1500,21 +1472,20 @@ gtk_css_provider_get_style (GtkStyleProvider *provider,
   for (i = 0; i < priv->rulesets->len; i++)
     {
       GtkCssRuleset *ruleset;
-      PropertyValue *value;
 
       ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
 
-      if (ruleset->style == NULL)
+      if (ruleset->styles == NULL)
         continue;
 
       if (!gtk_css_ruleset_matches (ruleset, path, 0))
         continue;
 
-      for (value = ruleset->style; value != NULL; value = value->next)
+      for (j = 0; j < ruleset->n_styles; j++)
 	_gtk_style_properties_set_property_by_property (props,
-							GTK_CSS_STYLE_PROPERTY (value->property),
+							GTK_CSS_STYLE_PROPERTY (ruleset->styles[i].property),
 							_gtk_css_selector_get_state_flags (ruleset->selector),
-							&value->value);
+							&ruleset->styles[i].value);
     }
 
   return props;
@@ -1606,6 +1577,7 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
   GtkCssProvider *css_provider;
   GtkCssProviderPrivate *priv;
   int i;
+  guint j;
 
   css_provider = GTK_CSS_PROVIDER (provider);
   priv = css_provider->priv;
@@ -1613,11 +1585,10 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
   for (i = priv->rulesets->len - 1; i >= 0; i--)
     {
       GtkCssRuleset *ruleset;
-      PropertyValue *value;
 
       ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
 
-      if (ruleset->style == NULL)
+      if (ruleset->styles == NULL)
         continue;
 
       if (!_gtk_bitmask_intersects (_gtk_css_lookup_get_missing (lookup),
@@ -1627,15 +1598,18 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
       if (!gtk_css_ruleset_matches (ruleset, path, state))
         continue;
 
-      for (value = ruleset->style; value != NULL; value = value->next)
+      for (j = 0; j < ruleset->n_styles; j++)
         {
-          GtkCssStyleProperty *prop = GTK_CSS_STYLE_PROPERTY (value->property);
+          GtkCssStyleProperty *prop = ruleset->styles[i].property;
           guint id = _gtk_css_style_property_get_id (prop);
 
           if (!_gtk_css_lookup_is_missing (lookup, id))
             continue;
 
-          _gtk_css_lookup_set (lookup, id, value->section, &value->value);
+          _gtk_css_lookup_set (lookup,
+                               id,
+                               ruleset->styles[i].section,
+                               &ruleset->styles[i].value);
         }
     }
 }
@@ -1759,7 +1733,7 @@ css_provider_commit (GtkCssProvider *css_provider,
 
   priv = css_provider->priv;
 
-  if (ruleset->style == NULL && ruleset->widget_style == NULL)
+  if (ruleset->styles == NULL && ruleset->widget_style == NULL)
     {
       g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
       return;
@@ -2469,21 +2443,13 @@ parse_declaration (GtkCssScanner *scanner,
                     {
                       GtkCssStyleProperty *child = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
                       const GValue *sub = &g_array_index (array, GValue, i);
-                      PropertyValue *val;
                       
-                      val = property_value_new (child, scanner->section);
-                      g_value_init (&val->value, G_VALUE_TYPE (sub));
-                      g_value_copy (sub, &val->value);
-                      gtk_css_ruleset_add (ruleset, child, val);
+                      gtk_css_ruleset_add (ruleset, child, sub, scanner->section);
                     }
                 }
               else if (GTK_IS_CSS_STYLE_PROPERTY (property))
                 {
-                  PropertyValue *val = property_value_new (GTK_CSS_STYLE_PROPERTY (property), scanner->section);
-
-                  g_value_init (&val->value, G_VALUE_TYPE (&value));
-                  g_value_copy (&value, &val->value);
-                  gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), val);
+                  gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), &value, scanner->section);
                 }
               else
                 {
@@ -3062,12 +3028,14 @@ gtk_css_provider_get_named (const gchar *name,
 }
 
 static int
-compare_properties (gconstpointer a, gconstpointer b)
+compare_properties (gconstpointer a, gconstpointer b, gpointer style)
 {
-  const PropertyValue *aa = a;
-  const PropertyValue *bb = b;
-  return strcmp (_gtk_style_property_get_name ((GtkStyleProperty *)aa->property),
-                 _gtk_style_property_get_name ((GtkStyleProperty *)bb->property));
+  const guint *ua = a;
+  const guint *ub = b;
+  PropertyValue *styles = style;
+
+  return strcmp (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (styles[*ua].property)),
+                 _gtk_style_property_get_name (GTK_STYLE_PROPERTY (styles[*ub].property)));
 }
 
 static int
@@ -3083,36 +3051,34 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
                        GString             *str)
 {
   GList *values, *walk;
-  PropertyValue *value;
   WidgetPropertyValue *widget_value;
+  guint i;
 
   _gtk_css_selector_print (ruleset->selector, str);
 
   g_string_append (str, " {\n");
 
-  if (ruleset->style)
+  if (ruleset->styles)
     {
-      values = NULL;
-      for (value = ruleset->style; value != NULL; value = value->next)
-	values = g_list_prepend (values, value);
+      guint *sorted = g_new (guint, ruleset->n_styles);
+
+      for (i = 0; i < ruleset->n_styles; i++)
+        sorted[i] = i;
 
       /* so the output is identical for identical selector styles */
-      values = g_list_sort (values, compare_properties);
+      g_qsort_with_data (sorted, ruleset->n_styles, sizeof (guint), compare_properties, ruleset->styles);
 
-      for (walk = values; walk; walk = walk->next)
+      for (i = 0; i < ruleset->n_styles; i++)
         {
-          GtkCssStyleProperty *prop;
-	  value = walk->data;
-	  prop = GTK_CSS_STYLE_PROPERTY (value->property);
-
+          PropertyValue *prop = &ruleset->styles[sorted[i]];
           g_string_append (str, "  ");
-          g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop)));
+          g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop->property)));
           g_string_append (str, ": ");
-          _gtk_css_style_property_print_value (prop, &value->value, str);
+          _gtk_css_style_property_print_value (prop->property, &prop->value, str);
           g_string_append (str, ";\n");
         }
 
-      g_list_free (values);
+      g_free (sorted);
     }
 
   if (ruleset->widget_style)



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