[gtk+] cssnode: Optimize listing of classes



commit 41b386cd6a84957dd9820083fa594090660c6a5d
Author: Garrett Regier <garrettregier gmail com>
Date:   Fri Sep 11 17:49:59 2015 +0200

    cssnode: Optimize listing of classes
    
    Avoid creating the GList of strings when the GQuarks
    will just be determined again. Instead have
    gtk_style_context_list_classes() do it specifically.

 gtk/gtkcssnode.c                   |   42 +++++++++++++++++------------------
 gtk/gtkcssnodedeclaration.c        |   22 +++++-------------
 gtk/gtkcssnodedeclarationprivate.h |    3 +-
 gtk/gtkcssnodeprivate.h            |    3 +-
 gtk/gtkstylecontext.c              |   16 ++++++++++---
 gtk/gtkwidget.c                    |   11 ++++-----
 gtk/gtkwidgetpath.c                |   19 +++++++++------
 gtk/gtkwidgetpath.h                |   14 ++++++++++++
 8 files changed, 72 insertions(+), 58 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 671613f..9b5db15 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -1054,16 +1054,15 @@ gtk_css_node_get_junction_sides (GtkCssNode *cssnode)
 static void
 gtk_css_node_clear_classes (GtkCssNode *cssnode)
 {
-  GList *list, *l;
-  
-  list = gtk_css_node_declaration_list_classes (cssnode->decl);
+  const GQuark *classes;
+  guint n_classes, i;
+
+  classes = gtk_css_node_declaration_get_classes (cssnode->decl, &n_classes);
 
-  for (l = list; l; l = l->next)
+  for (i = 0; i < n_classes; ++i)
     {
-      gtk_css_node_remove_class (cssnode, GPOINTER_TO_UINT (l->data));
+      gtk_css_node_remove_class (cssnode, classes[i]);
     }
-
-  g_list_free (list);
 }
 
 void
@@ -1090,22 +1089,20 @@ gtk_css_node_set_classes (GtkCssNode  *cssnode,
 char **
 gtk_css_node_get_classes (GtkCssNode *cssnode)
 {
-  GList *list, *l;
-  GPtrArray *result;
-  
-  list = gtk_css_node_declaration_list_classes (cssnode->decl);
-  result = g_ptr_array_new ();
+  const GQuark *classes;
+  char **result;
+  guint n_classes, i, j;
 
-  for (l = list; l; l = l->next)
+  classes = gtk_css_node_declaration_get_classes (cssnode->decl, &n_classes);
+  result = g_new (char *, n_classes + 1);
+
+  for (i = n_classes, j = 0; i-- > 0; ++j)
     {
-      g_ptr_array_add (result, g_strdup (g_quark_to_string (GPOINTER_TO_UINT (l->data))));
+      result[j] = g_strdup (g_quark_to_string (classes[i]));
     }
 
-  g_ptr_array_add (result, NULL);
-
-  g_list_free (list);
-
-  return (char **) g_ptr_array_free (result, FALSE);
+  result[n_classes] = NULL;
+  return result;
 }
 
 void
@@ -1137,10 +1134,11 @@ gtk_css_node_has_class (GtkCssNode *cssnode,
   return gtk_css_node_declaration_has_class (cssnode->decl, style_class);
 }
 
-GList *
-gtk_css_node_list_classes (GtkCssNode *cssnode)
+const GQuark *
+gtk_css_node_list_classes (GtkCssNode *cssnode,
+                           guint      *n_classes)
 {
-  return gtk_css_node_declaration_list_classes (cssnode->decl);
+  return gtk_css_node_declaration_get_classes (cssnode->decl, n_classes);
 }
 
 void
diff --git a/gtk/gtkcssnodedeclaration.c b/gtk/gtkcssnodedeclaration.c
index 221faef..c16189b 100644
--- a/gtk/gtkcssnodedeclaration.c
+++ b/gtk/gtkcssnodedeclaration.c
@@ -335,22 +335,13 @@ gtk_css_node_declaration_has_class (const GtkCssNodeDeclaration *decl,
     }
 }
 
-GList *
-gtk_css_node_declaration_list_classes (const GtkCssNodeDeclaration *decl)
+const GQuark *
+gtk_css_node_declaration_get_classes (const GtkCssNodeDeclaration *decl,
+                                      guint                       *n_classes)
 {
-  GQuark *classes;
-  GList *result;
-  guint i;
-
-  classes = get_classes (decl);
-  result = NULL;
-
-  for (i = 0; i < decl->n_classes; i++)
-    {
-      result = g_list_prepend (result, GUINT_TO_POINTER (classes[i]));
-    }
+  *n_classes = decl->n_classes;
 
-  return result;
+  return get_classes (decl);
 }
 
 static gboolean
@@ -589,8 +580,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
   classes = get_classes (decl);
   for (i = 0; i < decl->n_classes; i++)
     {
-      gtk_widget_path_iter_add_class (path, pos,
-                                      g_quark_to_string (classes[i]));
+      gtk_widget_path_iter_add_qclass (path, pos, classes[i]);
     }
 
   /* Set widget state */
diff --git a/gtk/gtkcssnodedeclarationprivate.h b/gtk/gtkcssnodedeclarationprivate.h
index 9e715fe..51c8c62 100644
--- a/gtk/gtkcssnodedeclarationprivate.h
+++ b/gtk/gtkcssnodedeclarationprivate.h
@@ -47,7 +47,8 @@ gboolean                gtk_css_node_declaration_remove_class           (GtkCssN
                                                                          GQuark                         
class_quark);
 gboolean                gtk_css_node_declaration_has_class              (const GtkCssNodeDeclaration   *decl,
                                                                          GQuark                         
class_quark);
-GList *                 gtk_css_node_declaration_list_classes           (const GtkCssNodeDeclaration   
*decl);
+const GQuark *          gtk_css_node_declaration_get_classes            (const GtkCssNodeDeclaration   *decl,
+                                                                         guint                         
*n_classes);
 
 gboolean                gtk_css_node_declaration_add_region             (GtkCssNodeDeclaration        **decl,
                                                                          GQuark                         
region_quark,
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index cbed7e8..9f1dc42 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -134,7 +134,8 @@ void                    gtk_css_node_remove_class       (GtkCssNode            *
                                                          GQuark                 style_class);
 gboolean                gtk_css_node_has_class          (GtkCssNode            *cssnode,
                                                          GQuark                 style_class);
-GList *                 gtk_css_node_list_classes       (GtkCssNode            *cssnode);
+const GQuark *          gtk_css_node_list_classes       (GtkCssNode            *cssnode,
+                                                         guint                 *n_classes);
 void                    gtk_css_node_add_region         (GtkCssNode            *cssnode,
                                                          GQuark                 region,
                                                          GtkRegionFlags         flags);
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index b359612..643a17b 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -1391,16 +1391,24 @@ GList *
 gtk_style_context_list_classes (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv;
-  GList *classes;
+  GList *classes_list;
+  const GQuark *classes;
+  guint n_classes, i;
+  const gchar *quark_str;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
 
   priv = context->priv;
   
-  classes = gtk_css_node_list_classes (priv->cssnode);
-  quarks_to_strings (classes);
+  classes = gtk_css_node_list_classes (priv->cssnode, &n_classes);
 
-  return classes;
+  for (i = n_classes; i-- > n_classes;)
+    {
+      quark_str = g_quark_to_string (classes[i]);
+      classes_list = g_list_prepend (classes_list, (gchar *) quark_str);
+    }
+
+  return classes_list;
 }
 
 /**
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 76207da..2652890 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -16333,17 +16333,16 @@ gtk_widget_path_append_for_widget (GtkWidgetPath *path,
 
   if (widget->priv->context)
     {
-      GList *classes, *l;
+      const GQuark *classes;
+      guint n_classes, i;
 
       /* Also add any persistent classes in
        * the style context the widget path
        */
-      classes = gtk_css_node_list_classes (widget->priv->cssnode);
+      classes = gtk_css_node_list_classes (widget->priv->cssnode, &n_classes);
 
-      for (l = classes; l; l = l->next)
-        gtk_widget_path_iter_add_class (path, pos, g_quark_to_string (GPOINTER_TO_UINT (l->data)));
-
-      g_list_free (classes);
+      for (i = n_classes; i-- > 0;)
+        gtk_widget_path_iter_add_qclass (path, pos, classes[i]);
     }
 
   return pos;
diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c
index e8a7ac7..f83af29 100644
--- a/gtk/gtkwidgetpath.c
+++ b/gtk/gtkwidgetpath.c
@@ -805,20 +805,23 @@ gtk_widget_path_iter_add_class (GtkWidgetPath *path,
                                 gint           pos,
                                 const gchar   *name)
 {
-  GtkPathElement *elem;
-  gboolean added = FALSE;
-  GQuark qname;
-  guint i;
-
   gtk_internal_return_if_fail (path != NULL);
   gtk_internal_return_if_fail (path->elems->len != 0);
   gtk_internal_return_if_fail (name != NULL);
 
-  if (pos < 0 || pos >= path->elems->len)
-    pos = path->elems->len - 1;
+  gtk_widget_path_iter_add_qclass (path, pos, g_quark_from_string (name));
+}
+
+void
+gtk_widget_path_iter_add_qclass (GtkWidgetPath *path,
+                                 gint           pos,
+                                 GQuark         qname)
+{
+  GtkPathElement *elem;
+  gboolean added = FALSE;
+  guint i;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  qname = g_quark_from_string (name);
 
   if (!elem->classes)
     elem->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
diff --git a/gtk/gtkwidgetpath.h b/gtk/gtkwidgetpath.h
index f1f7ad7..365c343 100644
--- a/gtk/gtkwidgetpath.h
+++ b/gtk/gtkwidgetpath.h
@@ -107,10 +107,18 @@ GDK_AVAILABLE_IN_ALL
 void     gtk_widget_path_iter_add_class     (GtkWidgetPath       *path,
                                              gint                 pos,
                                              const gchar         *name);
+GDK_AVAILABLE_IN_3_18
+void     gtk_widget_path_iter_add_qclass    (GtkWidgetPath       *path,
+                                             gint                 pos,
+                                             GQuark               qname);
 GDK_AVAILABLE_IN_ALL
 void     gtk_widget_path_iter_remove_class  (GtkWidgetPath       *path,
                                              gint                 pos,
                                              const gchar         *name);
+GDK_AVAILABLE_IN_3_18
+void     gtk_widget_path_iter_remove_qclass (GtkWidgetPath       *path,
+                                             gint                 pos,
+                                             GQuark               qname);
 GDK_AVAILABLE_IN_ALL
 void     gtk_widget_path_iter_clear_classes (GtkWidgetPath       *path,
                                              gint                 pos);
@@ -164,6 +172,12 @@ GDK_AVAILABLE_IN_ALL
 gboolean        gtk_widget_path_has_parent (const GtkWidgetPath *path,
                                             GType                type);
 
+/* private API goes here */
+
+void gtk_widget_path_iter_add_qclass       (GtkWidgetPath       *path,
+                                            gint                 pos,
+                                            GQuark               qname);
+
 G_END_DECLS
 
 #endif /* __GTK_WIDGET_PATH_H__ */


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