[gtk+/wip/css-bitmasks: 2/6] Initial version of using bitmaps for regions and styles



commit 1ffc8ebb8ae55018e62ff00e78f3524166a6d0ed
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Feb 7 23:36:43 2012 +0100

    Initial version of using bitmaps for regions and styles

 gtk/gtkstylecontext.c        |  341 +++++++++++++++++-------------------------
 gtk/gtkstylecontextprivate.h |   17 ++
 gtk/gtkwidgetpath.c          |  304 +++++++++++++++++--------------------
 3 files changed, 292 insertions(+), 370 deletions(-)
---
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index e497d1f..b117d71 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -307,12 +307,6 @@ typedef struct PropertyValue PropertyValue;
 typedef struct AnimationInfo AnimationInfo;
 typedef struct StyleData StyleData;
 
-struct GtkRegion
-{
-  GQuark class_quark;
-  GtkRegionFlags flags;
-};
-
 struct GtkStyleProviderData
 {
   GtkStyleProvider *provider;
@@ -329,8 +323,8 @@ struct PropertyValue
 
 struct GtkStyleInfo
 {
-  GArray *style_classes;
-  GArray *regions;
+  GtkBitmask *style_classes;
+  GtkBitmask *regions;
   GtkJunctionSides junction_sides;
   GtkStateFlags state_flags;
 };
@@ -477,8 +471,8 @@ style_info_new (void)
   GtkStyleInfo *info;
 
   info = g_slice_new0 (GtkStyleInfo);
-  info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
-  info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
+  info->style_classes = _gtk_bitmask_new ();
+  info->regions = _gtk_bitmask_new ();
 
   return info;
 }
@@ -486,8 +480,8 @@ style_info_new (void)
 static void
 style_info_free (GtkStyleInfo *info)
 {
-  g_array_free (info->style_classes, TRUE);
-  g_array_free (info->regions, TRUE);
+  _gtk_bitmask_free (info->style_classes);
+  _gtk_bitmask_free (info->regions);
   g_slice_free (GtkStyleInfo, info);
 }
 
@@ -497,13 +491,10 @@ style_info_copy (const GtkStyleInfo *info)
   GtkStyleInfo *copy;
 
   copy = style_info_new ();
-  g_array_insert_vals (copy->style_classes, 0,
-                       info->style_classes->data,
-                       info->style_classes->len);
-
-  g_array_insert_vals (copy->regions, 0,
-                       info->regions->data,
-                       info->regions->len);
+  _gtk_bitmask_union (copy->style_classes,
+		      info->style_classes);
+  _gtk_bitmask_union (copy->regions,
+		      info->regions);
 
   copy->junction_sides = info->junction_sides;
   copy->state_flags = info->state_flags;
@@ -515,25 +506,12 @@ static guint
 style_info_hash (gconstpointer elem)
 {
   const GtkStyleInfo *info;
-  guint i, hash = 0;
+  guint hash = 0;
 
   info = elem;
 
-  for (i = 0; i < info->style_classes->len; i++)
-    {
-      hash += g_array_index (info->style_classes, GQuark, i);
-      hash <<= 5;
-    }
-
-  for (i = 0; i < info->regions->len; i++)
-    {
-      GtkRegion *region;
-
-      region = &g_array_index (info->regions, GtkRegion, i);
-      hash += region->class_quark;
-      hash += region->flags;
-      hash <<= 5;
-    }
+  hash = _gtk_bitmask_hash (info->style_classes);
+  hash ^= _gtk_bitmask_hash (info->regions);
 
   return hash ^ info->state_flags;
 }
@@ -553,20 +531,12 @@ style_info_equal (gconstpointer elem1,
   if (info1->junction_sides != info2->junction_sides)
     return FALSE;
 
-  if (info1->style_classes->len != info2->style_classes->len)
-    return FALSE;
-
-  if (memcmp (info1->style_classes->data,
-              info2->style_classes->data,
-              info1->style_classes->len * sizeof (GQuark)) != 0)
-    return FALSE;
-
-  if (info1->regions->len != info2->regions->len)
+  if (!_gtk_bitmask_equals (info1->style_classes,
+			    info2->style_classes))
     return FALSE;
 
-  if (memcmp (info1->regions->data,
-              info2->regions->data,
-              info1->regions->len * sizeof (GtkRegion)) != 0)
+  if (!_gtk_bitmask_equals (info1->regions,
+			    info2->regions))
     return FALSE;
 
   return TRUE;
@@ -1034,7 +1004,7 @@ create_query_path (GtkStyleContext *context)
   GtkStyleContextPrivate *priv;
   GtkWidgetPath *path;
   GtkStyleInfo *info;
-  guint i, pos;
+  guint pos;
 
   priv = context->priv;
   path = gtk_widget_path_copy (priv->widget_path);
@@ -1042,26 +1012,11 @@ create_query_path (GtkStyleContext *context)
 
   info = priv->info_stack->data;
 
-  /* Set widget regions */
-  for (i = 0; i < info->regions->len; i++)
-    {
-      GtkRegion *region;
-
-      region = &g_array_index (info->regions, GtkRegion, i);
-      gtk_widget_path_iter_add_region (path, pos,
-                                       g_quark_to_string (region->class_quark),
-                                       region->flags);
-    }
+  _gtk_widget_path_iter_add_regions (path, pos,
+				     info->regions);
 
   /* Set widget classes */
-  for (i = 0; i < info->style_classes->len; i++)
-    {
-      GQuark quark;
-
-      quark = g_array_index (info->style_classes, GQuark, i);
-      gtk_widget_path_iter_add_class (path, pos,
-                                      g_quark_to_string (quark));
-    }
+  _gtk_widget_path_iter_add_classes (path, pos, info->style_classes);
 
   return path;
 }
@@ -1861,96 +1816,79 @@ gtk_style_context_restore (GtkStyleContext *context)
   priv->current_data = NULL;
 }
 
-static gboolean
-style_class_find (GArray *array,
-                  GQuark  class_quark,
-                  guint  *position)
-{
-  gint min, max, mid;
-  gboolean found = FALSE;
-  guint pos;
-
-  if (position)
-    *position = 0;
+static GHashTable *style_class_masks;
+static GPtrArray *style_class_masks_reverse;
+static guint style_class_masks_next;
+static GHashTable *style_region_masks;
+static GPtrArray *style_region_masks_reverse;
+static guint style_region_masks_next;
 
-  if (!array || array->len == 0)
-    return FALSE;
-
-  min = 0;
-  max = array->len - 1;
+guint
+_gtk_style_class_get_mask (const gchar *class_name)
+{
+  guint value;
+  gpointer ptr_value;
 
-  do
+  if (style_class_masks == NULL)
     {
-      GQuark item;
-
-      mid = (min + max) / 2;
-      item = g_array_index (array, GQuark, mid);
-
-      if (class_quark == item)
-        {
-          found = TRUE;
-          pos = mid;
-        }
-      else if (class_quark > item)
-        min = pos = mid + 1;
-      else
-        {
-          max = mid - 1;
-          pos = mid;
-        }
+      style_class_masks = g_hash_table_new (g_str_hash, g_str_equal);
+      style_class_masks_reverse = g_ptr_array_new ();
     }
-  while (!found && min <= max);
-
-  if (position)
-    *position = pos;
 
-  return found;
+  if (g_hash_table_lookup_extended (style_class_masks, class_name,
+				    NULL, &ptr_value))
+    value = GPOINTER_TO_INT (ptr_value);
+  else
+    {
+      const char *str = g_intern_string (class_name);
+      value = style_class_masks_next++;
+      ptr_value = GINT_TO_POINTER (value);
+      g_hash_table_insert (style_class_masks, str, ptr_value);
+      g_ptr_array_add (style_class_masks_reverse, str);
+    }
+  return value;
 }
 
-static gboolean
-region_find (GArray *array,
-             GQuark  class_quark,
-             guint  *position)
+const gchar *
+_gtk_style_class_get_name_from_mask (guint mask)
 {
-  gint min, max, mid;
-  gboolean found = FALSE;
-  guint pos;
-
-  if (position)
-    *position = 0;
-
-  if (!array || array->len == 0)
-    return FALSE;
+  if (mask < style_class_masks_next)
+    return g_ptr_array_index (style_class_masks_reverse, mask);
+  return NULL;
+}
 
-  min = 0;
-  max = array->len - 1;
+guint
+_gtk_style_region_get_mask (const gchar *region_name)
+{
+  guint value;
+  gpointer ptr_value;
 
-  do
+  if (style_region_masks == NULL)
     {
-      GtkRegion *region;
-
-      mid = (min + max) / 2;
-      region = &g_array_index (array, GtkRegion, mid);
-
-      if (region->class_quark == class_quark)
-        {
-          found = TRUE;
-          pos = mid;
-        }
-      else if (region->class_quark > class_quark)
-        min = pos = mid + 1;
-      else
-        {
-          max = mid - 1;
-          pos = mid;
-        }
+      style_region_masks = g_hash_table_new (g_str_hash, g_str_equal);
+      style_region_masks_reverse = g_ptr_array_new ();
     }
-  while (!found && min <= max);
 
-  if (position)
-    *position = pos;
+  if (g_hash_table_lookup_extended (style_region_masks, region_name,
+				    NULL, &ptr_value))
+    value = GPOINTER_TO_INT (ptr_value);
+  else
+    {
+      const char *str = g_intern_string (region_name);
+      value = style_region_masks_next++;
+      ptr_value = GINT_TO_POINTER (value);
+      g_hash_table_insert (style_region_masks, str, ptr_value);
+      g_ptr_array_add (style_region_masks_reverse, str);
+    }
+  return value;
+}
 
-  return found;
+const gchar *
+_gtk_style_region_get_name_from_mask (guint mask)
+{
+  if (mask < style_region_masks_next)
+    return g_ptr_array_index (style_region_masks_reverse, mask);
+  return NULL;
 }
 
 /**
@@ -1983,21 +1921,20 @@ gtk_style_context_add_class (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark class_quark;
-  guint position;
+  guint class_mask;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (class_name != NULL);
 
   priv = context->priv;
-  class_quark = g_quark_from_string (class_name);
+  class_mask = _gtk_style_class_get_mask (class_name);
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (!style_class_find (info->style_classes, class_quark, &position))
+  if (!_gtk_bitmask_get (info->style_classes, class_mask))
     {
-      g_array_insert_val (info->style_classes, position, class_quark);
+      _gtk_bitmask_set (info->style_classes, class_mask, TRUE);
 
       /* Unset current data, as it likely changed due to the class change */
       priv->current_data = NULL;
@@ -2019,25 +1956,21 @@ gtk_style_context_remove_class (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark class_quark;
-  guint position;
+  guint class_mask;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (class_name != NULL);
 
-  class_quark = g_quark_try_string (class_name);
-
-  if (!class_quark)
-    return;
+  class_mask = _gtk_style_class_get_mask (class_name);
 
   priv = context->priv;
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (style_class_find (info->style_classes, class_quark, &position))
+  if (_gtk_bitmask_get (info->style_classes, class_mask))
     {
-      g_array_remove_index (info->style_classes, position);
+      _gtk_bitmask_set (info->style_classes, class_mask, FALSE);
 
       /* Unset current data, as it likely changed due to the class change */
       priv->current_data = NULL;
@@ -2062,25 +1995,19 @@ gtk_style_context_has_class (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark class_quark;
+  guint class_mask;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
   g_return_val_if_fail (class_name != NULL, FALSE);
 
-  class_quark = g_quark_try_string (class_name);
-
-  if (!class_quark)
-    return FALSE;
+  class_mask = _gtk_style_class_get_mask (class_name);
 
   priv = context->priv;
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (style_class_find (info->style_classes, class_quark, NULL))
-    return TRUE;
-
-  return FALSE;
+  return _gtk_bitmask_get (info->style_classes, class_mask);
 }
 
 /**
@@ -2111,12 +2038,12 @@ gtk_style_context_list_classes (GtkStyleContext *context)
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  for (i = 0; i < info->style_classes->len; i++)
+  i = 0;
+  while (_gtk_bitmask_find_next_set (info->style_classes, &i))
     {
-      GQuark quark;
-
-      quark = g_array_index (info->style_classes, GQuark, i);
-      classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
+      classes = g_list_prepend (classes,
+				(gchar *) _gtk_style_class_get_name_from_mask (i));
+      i++;
     }
 
   return classes;
@@ -2150,15 +2077,16 @@ gtk_style_context_list_regions (GtkStyleContext *context)
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  for (i = 0; i < info->regions->len; i++)
+  i = 0;
+  while (_gtk_bitmask_find_next_set (info->regions, &i))
     {
-      GtkRegion *region;
-      const gchar *class_name;
+      guint region = i / GTK_REGION_FLAGS_NUM_BITS;
+      i = region * GTK_REGION_FLAGS_NUM_BITS;
 
-      region = &g_array_index (info->regions, GtkRegion, i);
+      classes = g_list_prepend (classes,
+				(gchar *)_gtk_style_region_get_name_from_mask (region));
 
-      class_name = g_quark_to_string (region->class_quark);
-      classes = g_list_prepend (classes, (gchar *) class_name);
+      i += GTK_REGION_FLAGS_NUM_BITS;
     }
 
   return classes;
@@ -2222,27 +2150,29 @@ gtk_style_context_add_region (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark region_quark;
-  guint position;
+  guint region;
+  guint i;
+  guint old_flags;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (region_name != NULL);
   g_return_if_fail (_gtk_style_context_check_region_name (region_name));
 
   priv = context->priv;
-  region_quark = g_quark_from_string (region_name);
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (!region_find (info->regions, region_quark, &position))
-    {
-      GtkRegion region;
+  region = _gtk_style_region_get_mask (region_name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
 
-      region.class_quark = region_quark;
-      region.flags = flags;
+  old_flags = _gtk_bitmask_get_uint (info->regions, i);
+  if ((old_flags & GTK_REGION_ADDED) == 0)
+    {
+      /* Ensure *some* flag is always set so we know this is added */
+      old_flags |= flags | GTK_REGION_ADDED;
 
-      g_array_insert_val (info->regions, position, region);
+      _gtk_bitmask_set_uint (info->regions, i, old_flags);
 
       /* Unset current data, as it likely changed due to the region change */
       priv->current_data = NULL;
@@ -2264,25 +2194,28 @@ gtk_style_context_remove_region (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark region_quark;
-  guint position;
+  guint region;
+  guint i, old_flags;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (region_name != NULL);
 
-  region_quark = g_quark_try_string (region_name);
-
-  if (!region_quark)
-    return;
-
   priv = context->priv;
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (region_find (info->regions, region_quark, &position))
+  region = _gtk_style_region_get_mask (region_name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
+
+  if (info->regions == NULL)
+    return;
+  
+  old_flags = _gtk_bitmask_get_uint (info->regions, i);
+  if ((old_flags & GTK_REGION_ADDED) != 0)
     {
-      g_array_remove_index (info->regions, position);
+      old_flags &= ~(GTK_REGION_FLAGS_MASK | GTK_REGION_ADDED);
+      _gtk_bitmask_set_uint (info->regions, i, old_flags);
 
       /* Unset current data, as it likely changed due to the region change */
       priv->current_data = NULL;
@@ -2310,8 +2243,8 @@ gtk_style_context_has_region (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleInfo *info;
-  GQuark region_quark;
-  guint position;
+  guint region;
+  guint i, flags;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
   g_return_val_if_fail (region_name != NULL, FALSE);
@@ -2319,25 +2252,19 @@ gtk_style_context_has_region (GtkStyleContext *context,
   if (flags_return)
     *flags_return = 0;
 
-  region_quark = g_quark_try_string (region_name);
-
-  if (!region_quark)
-    return FALSE;
-
   priv = context->priv;
 
   g_assert (priv->info_stack != NULL);
   info = priv->info_stack->data;
 
-  if (region_find (info->regions, region_quark, &position))
+  region = _gtk_style_region_get_mask (region_name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
+
+  flags = _gtk_bitmask_get_uint (info->regions, i);
+  if ((flags & GTK_REGION_ADDED) != 0)
     {
       if (flags_return)
-        {
-          GtkRegion *region;
-
-          region = &g_array_index (info->regions, GtkRegion, position);
-          *flags_return = region->flags;
-        }
+	*flags_return = flags & GTK_REGION_FLAGS_MASK;
       return TRUE;
     }
 
diff --git a/gtk/gtkstylecontextprivate.h b/gtk/gtkstylecontextprivate.h
index 59a8a69..90fb62c 100644
--- a/gtk/gtkstylecontextprivate.h
+++ b/gtk/gtkstylecontextprivate.h
@@ -22,6 +22,7 @@
 
 #include "gtkstylecontext.h"
 #include "gtksymboliccolor.h"
+#include "gtkbitmaskprivate.h"
 
 G_BEGIN_DECLS
 
@@ -46,6 +47,22 @@ void           _gtk_style_context_get_cursor_color           (GtkStyleContext *c
                                                               GdkRGBA         *primary_color,
                                                               GdkRGBA         *secondary_color);
 
+guint          _gtk_style_class_get_mask                     (const gchar     *class_name);
+const gchar *  _gtk_style_class_get_name_from_mask           (guint            mask);
+guint          _gtk_style_region_get_mask                    (const gchar     *region_name);
+const gchar *  _gtk_style_region_get_name_from_mask          (guint            mask);
+
+void            _gtk_widget_path_iter_add_classes            (GtkWidgetPath   *path,
+							      gint             pos,
+							      GtkBitmask      *classes);
+void            _gtk_widget_path_iter_add_regions            (GtkWidgetPath   *path,
+							      gint             pos,
+							      GtkBitmask      *regions);
+
+#define GTK_REGION_FLAGS_MASK  ((1 << 6) - 1)
+#define GTK_REGION_FLAGS_NUM_BITS 7
+#define GTK_REGION_ADDED (1 << 6)
+
 G_END_DECLS
 
 #endif /* __GTK_STYLE_CONTEXT_PRIVATE_H__ */
diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c
index 5720b38..0d90a0c 100644
--- a/gtk/gtkwidgetpath.c
+++ b/gtk/gtkwidgetpath.c
@@ -91,8 +91,8 @@ struct GtkPathElement
 {
   GType type;
   GQuark name;
-  GHashTable *regions;
-  GArray *classes;
+  GtkBitmask *regions;
+  GtkBitmask *classes;
   GtkWidgetPath *siblings;
   guint sibling_index;
 };
@@ -139,20 +139,14 @@ gtk_path_element_copy (GtkPathElement       *dest,
 
   if (src->regions)
     {
-      GHashTableIter iter;
-      gpointer key, value;
-
-      g_hash_table_iter_init (&iter, src->regions);
-      dest->regions = g_hash_table_new (NULL, NULL);
-
-      while (g_hash_table_iter_next (&iter, &key, &value))
-        g_hash_table_insert (dest->regions, key, value);
+      dest->regions = _gtk_bitmask_new ();
+      _gtk_bitmask_union (dest->regions, src->regions);
     }
 
   if (src->classes)
     {
-      dest->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
-      g_array_append_vals (dest->classes, src->classes->data, src->classes->len);
+      dest->classes = _gtk_bitmask_new ();
+      _gtk_bitmask_union (dest->classes, src->classes);
     }
 }
 
@@ -236,10 +230,10 @@ gtk_widget_path_unref (GtkWidgetPath *path)
       elem = &g_array_index (path->elems, GtkPathElement, i);
 
       if (elem->regions)
-        g_hash_table_destroy (elem->regions);
+        _gtk_bitmask_free (elem->regions);
 
       if (elem->classes)
-        g_array_free (elem->classes, TRUE);
+        _gtk_bitmask_free (elem->classes);
 
       if (elem->siblings)
         gtk_widget_path_unref (elem->siblings);
@@ -304,7 +298,8 @@ char *
 gtk_widget_path_to_string (const GtkWidgetPath *path)
 {
   GString *string;
-  guint i, j;
+  guint i, j, k;
+  guint pos;
 
   g_return_val_if_fail (path != NULL, NULL);
 
@@ -336,22 +331,23 @@ gtk_widget_path_to_string (const GtkWidgetPath *path)
 
       if (elem->classes)
         {
-          for (j = 0; j < elem->classes->len; j++)
-            {
+	  pos = 0;
+	  while (_gtk_bitmask_find_next_set (elem->classes, &pos))
+	    {
               g_string_append_c (string, '.');
-              g_string_append (string, g_quark_to_string (g_array_index (elem->classes, GQuark, j)));
-            }
+              g_string_append (string, 
+			       _gtk_style_class_get_name_from_mask (pos));
+	      pos++;
+	    }
         }
 
       if (elem->regions)
         {
-          GHashTableIter iter;
-          gpointer key, value;
-
-          g_hash_table_iter_init (&iter, elem->regions);
-          while (g_hash_table_iter_next (&iter, &key, &value))
-            {
-              GtkRegionFlags flags = GPOINTER_TO_UINT (value);
+	  k = 0;
+	  while (_gtk_bitmask_find_next_set (elem->regions, &k))
+	    {
+	      guint region = k / GTK_REGION_FLAGS_NUM_BITS;
+	      guint flags;
               static const char *flag_names[] = {
                 "even",
                 "odd",
@@ -361,8 +357,12 @@ gtk_widget_path_to_string (const GtkWidgetPath *path)
                 "sorted"
               };
 
+	      k = region * GTK_REGION_FLAGS_NUM_BITS;
+
+	      flags = _gtk_bitmask_get_uint (elem->regions, k);
+
               g_string_append_c (string, ' ');
-              g_string_append (string, g_quark_to_string (GPOINTER_TO_UINT (key)));
+              g_string_append (string, _gtk_style_region_get_name_from_mask (region));
               for (j = 0; j < G_N_ELEMENTS(flag_names); j++)
                 {
                   if (flags & (1 << j))
@@ -371,7 +371,9 @@ gtk_widget_path_to_string (const GtkWidgetPath *path)
                       g_string_append (string, flag_names[j]);
                     }
                 }
-            }
+	      
+	      k += GTK_REGION_FLAGS_NUM_BITS;
+	    }
         }
     }
 
@@ -715,9 +717,6 @@ gtk_widget_path_iter_add_class (GtkWidgetPath *path,
                                 const gchar   *name)
 {
   GtkPathElement *elem;
-  gboolean added = FALSE;
-  GQuark qname;
-  guint i;
 
   g_return_if_fail (path != NULL);
   g_return_if_fail (path->elems->len != 0);
@@ -727,33 +726,33 @@ gtk_widget_path_iter_add_class (GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   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));
+    elem->classes = _gtk_bitmask_new ();
 
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
+  _gtk_bitmask_set (elem->classes, _gtk_style_class_get_mask (name), TRUE);
+}
 
-      quark = g_array_index (elem->classes, GQuark, i);
+void
+_gtk_widget_path_iter_add_classes (GtkWidgetPath *path,
+				   gint           pos,
+				   GtkBitmask    *classes)
+{
+  GtkPathElement *elem;
 
-      if (qname == quark)
-        {
-          /* Already there */
-          added = TRUE;
-          break;
-        }
-      if (qname < quark)
-        {
-          g_array_insert_val (elem->classes, i, qname);
-          added = TRUE;
-          break;
-        }
-    }
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (path->elems->len != 0);
+  g_return_if_fail (classes != NULL);
+
+  if (pos < 0 || pos >= path->elems->len)
+    pos = path->elems->len - 1;
+
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!added)
-    g_array_append_val (elem->classes, qname);
+  if (!elem->classes)
+    elem->classes = _gtk_bitmask_new ();
+
+  _gtk_bitmask_union (elem->classes, classes);
 }
 
 /**
@@ -773,8 +772,6 @@ gtk_widget_path_iter_remove_class (GtkWidgetPath *path,
                                    const gchar   *name)
 {
   GtkPathElement *elem;
-  GQuark qname;
-  guint i;
 
   g_return_if_fail (path != NULL);
   g_return_if_fail (path->elems->len != 0);
@@ -783,30 +780,12 @@ gtk_widget_path_iter_remove_class (GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  qname = g_quark_try_string (name);
-
-  if (qname == 0)
-    return;
-
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
   if (!elem->classes)
-    return;
-
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
+    elem->classes = _gtk_bitmask_new ();
 
-      quark = g_array_index (elem->classes, GQuark, i);
-
-      if (quark > qname)
-        break;
-      else if (quark == qname)
-        {
-          g_array_remove_index (elem->classes, i);
-          break;
-        }
-    }
+  _gtk_bitmask_set (elem->classes, _gtk_style_class_get_mask (name), FALSE);
 }
 
 /**
@@ -836,8 +815,7 @@ gtk_widget_path_iter_clear_classes (GtkWidgetPath *path,
   if (!elem->classes)
     return;
 
-  if (elem->classes->len > 0)
-    g_array_remove_range (elem->classes, 0, elem->classes->len);
+  _gtk_bitmask_clear (elem->classes);
 }
 
 /**
@@ -874,12 +852,11 @@ gtk_widget_path_iter_list_classes (const GtkWidgetPath *path,
   if (!elem->classes)
     return NULL;
 
-  for (i = 0; i < elem->classes->len; i++)
+  i = 0;
+  while (_gtk_bitmask_find_next_set (elem->classes, &i))
     {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-      list = g_slist_prepend (list, (gchar *) g_quark_to_string (quark));
+      list = g_slist_prepend (list, (gchar *) _gtk_style_class_get_name_from_mask (i));
+      i++;
     }
 
   return g_slist_reverse (list);
@@ -903,34 +880,8 @@ gtk_widget_path_iter_has_qclass (const GtkWidgetPath *path,
                                  gint                 pos,
                                  GQuark               qname)
 {
-  GtkPathElement *elem;
-  guint i;
-
-  g_return_val_if_fail (path != NULL, FALSE);
-  g_return_val_if_fail (path->elems->len != 0, FALSE);
-  g_return_val_if_fail (qname != 0, FALSE);
-
-  if (pos < 0 || pos >= path->elems->len)
-    pos = path->elems->len - 1;
-
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
-  if (!elem->classes)
-    return FALSE;
-
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-
-      if (quark == qname)
-        return TRUE;
-      else if (quark > qname)
-        break;
-    }
-
-  return FALSE;
+  return gtk_widget_path_iter_has_class (path, pos,
+					 g_quark_to_string (qname));
 }
 
 /**
@@ -951,7 +902,8 @@ gtk_widget_path_iter_has_class (const GtkWidgetPath *path,
                                 gint                 pos,
                                 const gchar         *name)
 {
-  GQuark qname;
+  GtkPathElement *elem;
+  guint mask;
 
   g_return_val_if_fail (path != NULL, FALSE);
   g_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -960,12 +912,14 @@ gtk_widget_path_iter_has_class (const GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  qname = g_quark_try_string (name);
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (qname == 0)
+  if (!elem->classes)
     return FALSE;
 
-  return gtk_widget_path_iter_has_qclass (path, pos, qname);
+  mask = _gtk_style_class_get_mask (name);
+
+  return _gtk_bitmask_get (elem->classes, mask);
 }
 
 /**
@@ -991,7 +945,9 @@ gtk_widget_path_iter_add_region (GtkWidgetPath  *path,
                                  GtkRegionFlags  flags)
 {
   GtkPathElement *elem;
-  GQuark qname;
+  guint region;
+  guint i;
+  guint old_flags;
 
   g_return_if_fail (path != NULL);
   g_return_if_fail (path->elems->len != 0);
@@ -1002,14 +958,40 @@ gtk_widget_path_iter_add_region (GtkWidgetPath  *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  qname = g_quark_from_string (name);
 
   if (!elem->regions)
-    elem->regions = g_hash_table_new (NULL, NULL);
+    elem->regions = _gtk_bitmask_new ();
+
+  region = _gtk_style_region_get_mask (name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
+
+  old_flags = _gtk_bitmask_get_uint (elem->regions, i);
+  old_flags &= ~(GTK_REGION_FLAGS_MASK | GTK_REGION_ADDED);
+  /* Ensure *some* flag is always set so we know this is added */
+  old_flags |= flags | GTK_REGION_ADDED;
+  _gtk_bitmask_set_uint (elem->regions, i, old_flags);
+}
+
+void
+_gtk_widget_path_iter_add_regions (GtkWidgetPath  *path,
+				   gint            pos,
+				   GtkBitmask     *regions)
+{
+  GtkPathElement *elem;
+
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (path->elems->len != 0);
+  g_return_if_fail (regions != NULL);
+
+  if (pos < 0 || pos >= path->elems->len)
+    pos = path->elems->len - 1;
+
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
+
+  if (!elem->regions)
+    elem->regions = _gtk_bitmask_new ();
 
-  g_hash_table_insert (elem->regions,
-                       GUINT_TO_POINTER (qname),
-                       GUINT_TO_POINTER (flags));
+  _gtk_bitmask_union (elem->regions, regions);
 }
 
 /**
@@ -1029,7 +1011,9 @@ gtk_widget_path_iter_remove_region (GtkWidgetPath *path,
                                     const gchar   *name)
 {
   GtkPathElement *elem;
-  GQuark qname;
+  guint region;
+  guint i;
+  guint old_flags;
 
   g_return_if_fail (path != NULL);
   g_return_if_fail (path->elems->len != 0);
@@ -1038,15 +1022,17 @@ gtk_widget_path_iter_remove_region (GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  qname = g_quark_try_string (name);
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (qname == 0)
+  if (elem->regions == NULL)
     return;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  region = _gtk_style_region_get_mask (name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
 
-  if (elem->regions)
-    g_hash_table_remove (elem->regions, GUINT_TO_POINTER (qname));
+  old_flags = _gtk_bitmask_get_uint (elem->regions, i);
+  old_flags &= ~(GTK_REGION_FLAGS_MASK | GTK_REGION_ADDED);
+  _gtk_bitmask_set_uint (elem->regions, i, old_flags);
 }
 
 /**
@@ -1074,7 +1060,7 @@ gtk_widget_path_iter_clear_regions (GtkWidgetPath *path,
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
   if (elem->regions)
-    g_hash_table_remove_all (elem->regions);
+    _gtk_bitmask_clear (elem->regions);
 }
 
 /**
@@ -1097,9 +1083,8 @@ gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
                                    gint                 pos)
 {
   GtkPathElement *elem;
-  GHashTableIter iter;
   GSList *list = NULL;
-  gpointer key;
+  guint i;
 
   g_return_val_if_fail (path != NULL, NULL);
   g_return_val_if_fail (path->elems->len != 0, NULL);
@@ -1112,14 +1097,16 @@ gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
   if (!elem->regions)
     return NULL;
 
-  g_hash_table_iter_init (&iter, elem->regions);
-
-  while (g_hash_table_iter_next (&iter, &key, NULL))
+  i = 0;
+  while (_gtk_bitmask_find_next_set (elem->regions, &i))
     {
-      GQuark qname;
+      guint region = i / GTK_REGION_FLAGS_NUM_BITS;
+      i = region * GTK_REGION_FLAGS_NUM_BITS;
 
-      qname = GPOINTER_TO_UINT (key);
-      list = g_slist_prepend (list, (gchar *) g_quark_to_string (qname));
+      list = g_slist_prepend (list,
+			      (gchar *) _gtk_style_region_get_name_from_mask (region));
+
+      i += GTK_REGION_FLAGS_NUM_BITS;
     }
 
   return list;
@@ -1145,30 +1132,8 @@ gtk_widget_path_iter_has_qregion (const GtkWidgetPath *path,
                                   GQuark               qname,
                                   GtkRegionFlags      *flags)
 {
-  GtkPathElement *elem;
-  gpointer value;
-
-  g_return_val_if_fail (path != NULL, FALSE);
-  g_return_val_if_fail (path->elems->len != 0, FALSE);
-  g_return_val_if_fail (qname != 0, FALSE);
-
-  if (pos < 0 || pos >= path->elems->len)
-    pos = path->elems->len - 1;
-
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
-  if (!elem->regions)
-    return FALSE;
-
-  if (!g_hash_table_lookup_extended (elem->regions,
-                                     GUINT_TO_POINTER (qname),
-                                     NULL, &value))
-    return FALSE;
-
-  if (flags)
-    *flags = GPOINTER_TO_UINT (value);
-
-  return TRUE;
+  return gtk_widget_path_iter_has_region (path, pos,
+					  g_quark_to_string (qname), flags);
 }
 
 /**
@@ -1189,9 +1154,11 @@ gboolean
 gtk_widget_path_iter_has_region (const GtkWidgetPath *path,
                                  gint                 pos,
                                  const gchar         *name,
-                                 GtkRegionFlags      *flags)
+                                 GtkRegionFlags      *flags_return)
 {
-  GQuark qname;
+  GtkPathElement *elem;
+  guint region;
+  guint i, flags;
 
   g_return_val_if_fail (path != NULL, FALSE);
   g_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -1200,12 +1167,23 @@ gtk_widget_path_iter_has_region (const GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  qname = g_quark_try_string (name);
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (qname == 0)
+  if (!elem->regions)
     return FALSE;
 
-  return gtk_widget_path_iter_has_qregion (path, pos, qname, flags);
+  region = _gtk_style_region_get_mask (name);
+  i = region * GTK_REGION_FLAGS_NUM_BITS;
+
+  flags = _gtk_bitmask_get_uint (elem->regions, i);
+  if ((flags & GTK_REGION_ADDED) != 0)
+    {
+      if (flags_return)
+	*flags_return = flags & GTK_REGION_FLAGS_MASK;
+      return TRUE;
+    }
+
+  return FALSE;
 }
 
 /**



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