[gtk+] cssnode: Redo first/last-child change tracking



commit 2e362eafc7a22e007fddb4ee9c76dfffdbbf02b7
Author: Benjamin Otte <otte redhat com>
Date:   Wed Dec 16 19:48:30 2015 +0100

    cssnode: Redo first/last-child change tracking
    
    Invisible nodes don't change the first/last-child status of the nodes
    after/before them. That means we don't have to just check the state of
    the adjacent node when modifying this state, but all their siblings
    until we hit a visible node.
    
    The same way, a node is not the first child if it has no previous
    sibling, it is the first child if it has no previous visible sibling.
    This is important for caching in the global lookup cache.

 gtk/gtkcssnode.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 738d1e9..b129c01 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -253,6 +253,36 @@ gtk_css_node_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_css_node_parent_class)->finalize (object);
 }
 
+static gboolean
+gtk_css_node_is_first_child (GtkCssNode *node)
+{
+  GtkCssNode *iter;
+
+  for (iter = node->previous_sibling;
+       iter != NULL;
+       iter = iter->previous_sibling)
+    {
+      if (iter->visible)
+        return FALSE;
+    }
+  return TRUE;
+}
+
+static gboolean
+gtk_css_node_is_last_child (GtkCssNode *node)
+{
+  GtkCssNode *iter;
+
+  for (iter = node->next_sibling;
+       iter != NULL;
+       iter = iter->next_sibling)
+    {
+      if (iter->visible)
+        return FALSE;
+    }
+  return TRUE;
+}
+
 #define UNPACK_DECLARATION(packed) ((GtkCssNodeDeclaration *) (GPOINTER_TO_SIZE (packed) & ~0x3))
 #define UNPACK_FLAGS(packed) (GPOINTER_TO_SIZE (packed) & 0x3)
 #define PACK(decl, first_child, last_child) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (decl) | ((first_child) ? 0x2 
: 0) | ((last_child) ? 0x1 : 0))
@@ -292,8 +322,8 @@ lookup_in_global_parent_cache (GtkCssNode                  *node,
 
   style = g_hash_table_lookup (cache,
                                PACK (decl,
-                                     gtk_css_node_get_previous_sibling (node) == NULL,
-                                     gtk_css_node_get_next_sibling (node) == NULL));
+                                     gtk_css_node_is_first_child (node),
+                                     gtk_css_node_is_last_child (node)));
 
   return style;
 }
@@ -376,8 +406,8 @@ store_in_global_parent_cache (GtkCssNode                  *node,
 
   g_hash_table_insert (cache,
                        PACK (gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl),
-                             gtk_css_node_get_previous_sibling (node) == NULL,
-                             gtk_css_node_get_next_sibling (node) == NULL),
+                             gtk_css_node_is_first_child (node),
+                             gtk_css_node_is_last_child (node)),
                        g_object_ref (style));
 }
 
@@ -1071,6 +1101,8 @@ void
 gtk_css_node_set_visible (GtkCssNode *cssnode,
                           gboolean    visible)
 {
+  GtkCssNode *iter;
+
   if (cssnode->visible == visible)
     return;
 
@@ -1094,14 +1126,34 @@ gtk_css_node_set_visible (GtkCssNode *cssnode,
     }
 
   if (cssnode->next_sibling)
-    gtk_css_node_invalidate (cssnode->next_sibling, GTK_CSS_CHANGE_ANY_SIBLING
-                                                    | GTK_CSS_CHANGE_NTH_CHILD
-                                                    | (cssnode->previous_sibling ? 0 : 
GTK_CSS_CHANGE_FIRST_CHILD));
-
+    {
+      gtk_css_node_invalidate (cssnode->next_sibling, GTK_CSS_CHANGE_ANY_SIBLING | GTK_CSS_CHANGE_NTH_CHILD);
+      if (gtk_css_node_is_first_child (cssnode))
+        {
+          for (iter = cssnode->next_sibling;
+               iter != NULL;
+               iter = iter->next_sibling)
+            {
+              gtk_css_node_invalidate (iter, GTK_CSS_CHANGE_FIRST_CHILD);
+              if (iter->visible)
+                break;
+            }
+        }
+    }
+               
   if (cssnode->previous_sibling)
     {
-      if (cssnode->next_sibling)
-        gtk_css_node_invalidate (cssnode->previous_sibling, GTK_CSS_CHANGE_LAST_CHILD);
+      if (gtk_css_node_is_last_child (cssnode))
+        {
+          for (iter = cssnode->previous_sibling;
+               iter != NULL;
+               iter = iter->previous_sibling)
+            {
+              gtk_css_node_invalidate (iter, GTK_CSS_CHANGE_LAST_CHILD);
+              if (iter->visible)
+                break;
+            }
+        }
       gtk_css_node_invalidate (cssnode->parent->first_child, GTK_CSS_CHANGE_NTH_LAST_CHILD);
     }
 }


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