forked from AuroraMiddleware/gtk
css: Add fast-path for parent selector matching
Add a fast path for parent selector matching that uses a bloom filter to quickly discard selectors that can't possibly match. Keep in mind that we match using a bloom filter, so we might accidentally include too many selectors when hash/bucket collisions occur. That's not a correctness problem though, because we'll do a real check afterwards. The idea for this change is taken from browsers, in particular WebKit.
This commit is contained in:
parent
6aac56e144
commit
170130f1d9
158
gtk/gtkcountingbloomfilterprivate.h
Normal file
158
gtk/gtkcountingbloomfilterprivate.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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.1 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_COUNTING_BLOOM_FILTER_PRIVATE_H__
|
||||
#define __GTK_COUNTING_BLOOM_FILTER_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* SECTION:gtkcountingbloomfilter
|
||||
* @Short_description: A counting bloom filter
|
||||
* @Title: GtkCountingBloomFilter
|
||||
* @See_also: https://en.wikipedia.org/wiki/Bloom_filter,
|
||||
* https://en.wikipedia.org/wiki/Counting_Bloom_filter
|
||||
*
|
||||
* This implements a counting bloom filter. A bloom filter is a space-efficient
|
||||
* probabilistic data structure that is used to test whether an element may be
|
||||
* a member of a set.
|
||||
* The Wikipedia links provide a lot more details into how and why this data
|
||||
* structure works and when to use it.
|
||||
*
|
||||
* This implementation is based on similar implementations in web browsers, because it's
|
||||
* original use case is the same: Making CSS lookups fast.
|
||||
*
|
||||
* As such, the number of bits is hardcoded to 12 and the elements in the set
|
||||
* are 16bit hash values.
|
||||
* It is possible to use 32bit hash values or a different number of bits, should this
|
||||
* be considered useful.
|
||||
*/
|
||||
|
||||
/* The number of bits from the hash we care about */
|
||||
#define GTK_COUNTING_BLOOM_FILTER_BITS (12)
|
||||
|
||||
/* The necessary size of the filter */
|
||||
#define GTK_COUNTING_BLOOM_FILTER_SIZE (1 << GTK_COUNTING_BLOOM_FILTER_BITS)
|
||||
|
||||
typedef struct _GtkCountingBloomFilter GtkCountingBloomFilter;
|
||||
|
||||
struct _GtkCountingBloomFilter
|
||||
{
|
||||
guint8 buckets[GTK_COUNTING_BLOOM_FILTER_SIZE];
|
||||
};
|
||||
|
||||
static inline void gtk_counting_bloom_filter_add (GtkCountingBloomFilter *self,
|
||||
guint16 hash);
|
||||
static inline void gtk_counting_bloom_filter_remove (GtkCountingBloomFilter *self,
|
||||
guint16 hash);
|
||||
static inline gboolean gtk_counting_bloom_filter_may_contain (const GtkCountingBloomFilter *self,
|
||||
guint16 hash);
|
||||
|
||||
|
||||
/*
|
||||
* GTK_COUNTING_BLOOM_FILTER_INIT:
|
||||
*
|
||||
* Initialize the bloom filter. As bloom filters are always stack-allocated,
|
||||
* initialization should happen when defining them, like:
|
||||
* ```c
|
||||
* GtkCountingBloomFilter filter = GTK_COUNTING_BLOOM_FILTER_INIT;
|
||||
* ```
|
||||
*
|
||||
* The filter does not need to be freed.
|
||||
*/
|
||||
#define GTK_COUNTING_BLOOM_FILTER_INIT { 0, }
|
||||
|
||||
/*
|
||||
* gtk_counting_bloom_filter_add:
|
||||
* @self: a #GtkCountingBloomFilter
|
||||
* @hash: a hash value to add to the filter
|
||||
*
|
||||
* Adds the hash value to the filter.
|
||||
*
|
||||
* If the same hash value gets added multiple times, it will
|
||||
* be considered as contained in the hash until it has been
|
||||
* removed as many times.
|
||||
**/
|
||||
static inline void
|
||||
gtk_counting_bloom_filter_add (GtkCountingBloomFilter *self,
|
||||
guint16 hash)
|
||||
{
|
||||
guint16 bucket = hash % GTK_COUNTING_BLOOM_FILTER_SIZE;
|
||||
|
||||
if (self->buckets[bucket] == 255)
|
||||
return;
|
||||
|
||||
self->buckets[bucket]++;
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_counting_bloom_filter_remove:
|
||||
* @self: a #GtkCountingBloomFilter
|
||||
* @hash: a hash value to remove from the filter
|
||||
*
|
||||
* Removes a hash value from the filter that has previously
|
||||
* been added via gtk_counting_bloom_filter_add().
|
||||
**/
|
||||
static inline void
|
||||
gtk_counting_bloom_filter_remove (GtkCountingBloomFilter *self,
|
||||
guint16 hash)
|
||||
{
|
||||
guint16 bucket = hash % GTK_COUNTING_BLOOM_FILTER_SIZE;
|
||||
|
||||
if (self->buckets[bucket] == 255)
|
||||
return;
|
||||
|
||||
g_assert (self->buckets[bucket] > 0);
|
||||
|
||||
self->buckets[bucket]--;
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_counting_bloom_filter_may_contain:
|
||||
* @self: a #GtkCountingBloomFilter
|
||||
* @hash: the hash value to check
|
||||
*
|
||||
* Checks if @hash may be contained in @self.
|
||||
*
|
||||
* A return value of %FALSE means that @hash is definitely not part
|
||||
* of @self.
|
||||
*
|
||||
* A return value of %TRUE means that @hash may or may not have been
|
||||
* added to @self. In that case a different method must be used to
|
||||
* confirm that @hash is indeed part of the set.
|
||||
*
|
||||
* Returns: %FALSE if @hash is not part of @self.
|
||||
**/
|
||||
static inline gboolean
|
||||
gtk_counting_bloom_filter_may_contain (const GtkCountingBloomFilter *self,
|
||||
guint16 hash)
|
||||
{
|
||||
guint16 bucket = hash % GTK_COUNTING_BLOOM_FILTER_SIZE;
|
||||
|
||||
return self->buckets[bucket] != 0;
|
||||
}
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __GTK_COUNTING_BLOOM_FILTER_PRIVATE_H_ */
|
@ -355,6 +355,7 @@ store_in_global_parent_cache (GtkCssNode *node,
|
||||
|
||||
static GtkCssStyle *
|
||||
gtk_css_node_create_style (GtkCssNode *cssnode,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssChange change)
|
||||
{
|
||||
const GtkCssNodeDeclaration *decl;
|
||||
@ -380,6 +381,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode,
|
||||
}
|
||||
|
||||
style = gtk_css_static_style_new_compute (gtk_css_node_get_style_provider (cssnode),
|
||||
filter,
|
||||
cssnode,
|
||||
style_change);
|
||||
|
||||
@ -412,6 +414,7 @@ gtk_css_style_needs_recreation (GtkCssStyle *style,
|
||||
|
||||
static GtkCssStyle *
|
||||
gtk_css_node_real_update_style (GtkCssNode *cssnode,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssChange change,
|
||||
gint64 timestamp,
|
||||
GtkCssStyle *style)
|
||||
@ -421,7 +424,7 @@ gtk_css_node_real_update_style (GtkCssNode *cssnode,
|
||||
static_style = GTK_CSS_STYLE (gtk_css_style_get_static_style (style));
|
||||
|
||||
if (gtk_css_style_needs_recreation (static_style, change))
|
||||
new_static_style = gtk_css_node_create_style (cssnode, change);
|
||||
new_static_style = gtk_css_node_create_style (cssnode, filter, change);
|
||||
else
|
||||
new_static_style = g_object_ref (static_style);
|
||||
|
||||
@ -951,6 +954,7 @@ gtk_css_node_needs_new_style (GtkCssNode *cssnode)
|
||||
|
||||
static void
|
||||
gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
gint64 current_time)
|
||||
{
|
||||
gboolean style_changed;
|
||||
@ -959,18 +963,19 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
||||
return;
|
||||
|
||||
if (cssnode->parent)
|
||||
gtk_css_node_ensure_style (cssnode->parent, current_time);
|
||||
gtk_css_node_ensure_style (cssnode->parent, filter, current_time);
|
||||
|
||||
if (cssnode->style_is_invalid)
|
||||
{
|
||||
GtkCssStyle *new_style;
|
||||
|
||||
if (cssnode->previous_sibling)
|
||||
gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
|
||||
gtk_css_node_ensure_style (cssnode->previous_sibling, filter, current_time);
|
||||
|
||||
g_clear_pointer (&cssnode->cache, gtk_css_node_style_cache_unref);
|
||||
|
||||
new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
|
||||
filter,
|
||||
cssnode->pending_changes,
|
||||
current_time,
|
||||
cssnode->style);
|
||||
@ -996,7 +1001,7 @@ gtk_css_node_get_style (GtkCssNode *cssnode)
|
||||
{
|
||||
gint64 timestamp = gtk_css_node_get_timestamp (cssnode);
|
||||
|
||||
gtk_css_node_ensure_style (cssnode, timestamp);
|
||||
gtk_css_node_ensure_style (cssnode, NULL, timestamp);
|
||||
}
|
||||
|
||||
return cssnode->style;
|
||||
@ -1301,14 +1306,16 @@ gtk_css_node_invalidate (GtkCssNode *cssnode,
|
||||
|
||||
static void
|
||||
gtk_css_node_validate_internal (GtkCssNode *cssnode,
|
||||
GtkCountingBloomFilter *filter,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GtkCssNode *child;
|
||||
gboolean bloomed = FALSE;
|
||||
|
||||
if (!cssnode->invalid)
|
||||
return;
|
||||
|
||||
gtk_css_node_ensure_style (cssnode, timestamp);
|
||||
gtk_css_node_ensure_style (cssnode, filter, timestamp);
|
||||
|
||||
/* need to set to FALSE then to TRUE here to make it chain up */
|
||||
gtk_css_node_set_invalid (cssnode, FALSE);
|
||||
@ -1321,20 +1328,32 @@ gtk_css_node_validate_internal (GtkCssNode *cssnode,
|
||||
child;
|
||||
child = gtk_css_node_get_next_sibling (child))
|
||||
{
|
||||
if (child->visible)
|
||||
gtk_css_node_validate_internal (child, timestamp);
|
||||
if (!child->visible)
|
||||
continue;
|
||||
|
||||
if (!bloomed)
|
||||
{
|
||||
gtk_css_node_declaration_add_bloom_hashes (cssnode->decl, filter);
|
||||
bloomed = TRUE;
|
||||
}
|
||||
|
||||
gtk_css_node_validate_internal (child, filter, timestamp);
|
||||
}
|
||||
|
||||
if (bloomed)
|
||||
gtk_css_node_declaration_remove_bloom_hashes (cssnode->decl, filter);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_validate (GtkCssNode *cssnode)
|
||||
{
|
||||
GtkCountingBloomFilter filter = GTK_COUNTING_BLOOM_FILTER_INIT;
|
||||
gint64 timestamp;
|
||||
gint64 before = g_get_monotonic_time ();
|
||||
|
||||
timestamp = gtk_css_node_get_timestamp (cssnode);
|
||||
|
||||
gtk_css_node_validate_internal (cssnode, timestamp);
|
||||
gtk_css_node_validate_internal (cssnode, &filter, timestamp);
|
||||
|
||||
if (cssnode->parent == NULL)
|
||||
{
|
||||
|
@ -312,6 +312,40 @@ gtk_css_node_declaration_get_classes (const GtkCssNodeDeclaration *decl,
|
||||
return decl->classes;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_declaration_add_bloom_hashes (const GtkCssNodeDeclaration *decl,
|
||||
GtkCountingBloomFilter *filter)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (decl->name)
|
||||
gtk_counting_bloom_filter_add (filter, gtk_css_hash_name (decl->name));
|
||||
if (decl->id)
|
||||
gtk_counting_bloom_filter_add (filter, gtk_css_hash_id (decl->id));
|
||||
|
||||
for (i = 0; i < decl->n_classes; i++)
|
||||
{
|
||||
gtk_counting_bloom_filter_add (filter, gtk_css_hash_class (decl->classes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_declaration_remove_bloom_hashes (const GtkCssNodeDeclaration *decl,
|
||||
GtkCountingBloomFilter *filter)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (decl->name)
|
||||
gtk_counting_bloom_filter_remove (filter, gtk_css_hash_name (decl->name));
|
||||
if (decl->id)
|
||||
gtk_counting_bloom_filter_remove (filter, gtk_css_hash_id (decl->id));
|
||||
|
||||
for (i = 0; i < decl->n_classes; i++)
|
||||
{
|
||||
gtk_counting_bloom_filter_remove (filter, gtk_css_hash_class (decl->classes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_css_node_declaration_hash (gconstpointer elem)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef __GTK_CSS_NODE_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_NODE_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtkcountingbloomfilterprivate.h"
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkenums.h"
|
||||
|
||||
@ -47,6 +48,11 @@ gboolean gtk_css_node_declaration_has_class (const G
|
||||
const GQuark * gtk_css_node_declaration_get_classes (const GtkCssNodeDeclaration *decl,
|
||||
guint *n_classes);
|
||||
|
||||
void gtk_css_node_declaration_add_bloom_hashes (const GtkCssNodeDeclaration *decl,
|
||||
GtkCountingBloomFilter *filter);
|
||||
void gtk_css_node_declaration_remove_bloom_hashes (const GtkCssNodeDeclaration *decl,
|
||||
GtkCountingBloomFilter *filter);
|
||||
|
||||
guint gtk_css_node_declaration_hash (gconstpointer elem);
|
||||
gboolean gtk_css_node_declaration_equal (gconstpointer elem1,
|
||||
gconstpointer elem2);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef __GTK_CSS_NODE_PRIVATE_H__
|
||||
#define __GTK_CSS_NODE_PRIVATE_H__
|
||||
|
||||
#include "gtkcountingbloomfilterprivate.h"
|
||||
#include "gtkcssnodedeclarationprivate.h"
|
||||
#include "gtkcssnodestylecacheprivate.h"
|
||||
#include "gtkcssstylechangeprivate.h"
|
||||
@ -81,6 +82,7 @@ struct _GtkCssNodeClass
|
||||
/* get frame clock or NULL (only relevant for root node) */
|
||||
GdkFrameClock * (* get_frame_clock) (GtkCssNode *cssnode);
|
||||
GtkCssStyle * (* update_style) (GtkCssNode *cssnode,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssChange pending_changes,
|
||||
gint64 timestamp,
|
||||
GtkCssStyle *old_style);
|
||||
|
@ -449,6 +449,7 @@ gtk_css_style_provider_get_keyframes (GtkStyleProvider *provider,
|
||||
|
||||
static void
|
||||
gtk_css_style_provider_lookup (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssLookup *lookup,
|
||||
GtkCssChange *change)
|
||||
@ -463,7 +464,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
|
||||
if (_gtk_css_selector_tree_is_empty (priv->tree))
|
||||
return;
|
||||
|
||||
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, node);
|
||||
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, filter, node);
|
||||
if (tree_rules)
|
||||
{
|
||||
verify_tree_match_results (css_provider, node, tree_rules);
|
||||
|
@ -168,24 +168,6 @@ g_ptr_array_insert_sorted (GPtrArray *array,
|
||||
g_ptr_array_insert (array, i, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
||||
GPtrArray **array)
|
||||
{
|
||||
int i;
|
||||
gpointer *matches;
|
||||
|
||||
matches = gtk_css_selector_tree_get_matches (tree);
|
||||
if (matches)
|
||||
{
|
||||
if (!*array)
|
||||
*array = g_ptr_array_sized_new (16);
|
||||
|
||||
for (i = 0; matches[i] != NULL; i++)
|
||||
g_ptr_array_insert_sorted (*array, matches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gtk_css_selector_match (const GtkCssSelector *selector,
|
||||
GtkCssNode *node)
|
||||
@ -1864,38 +1846,115 @@ gtk_css_selectors_skip_initial_selector (GtkCssSelector *selector, const GtkCssS
|
||||
return (GtkCssSelector *)gtk_css_selector_previous (selector);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_selector_tree_match_bloom (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
gboolean skipping)
|
||||
{
|
||||
const GtkCssSelectorTree *prev;
|
||||
|
||||
switch (tree->selector.class->category)
|
||||
{
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE:
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL:
|
||||
if (skipping)
|
||||
break;
|
||||
if (!gtk_counting_bloom_filter_may_contain (filter,
|
||||
gtk_css_selector_hash_one (&tree->selector)))
|
||||
return FALSE;
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_PARENT:
|
||||
skipping = FALSE;
|
||||
break;
|
||||
case GTK_CSS_SELECTOR_CATEGORY_SIBLING:
|
||||
skipping = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gtk_css_selector_tree_get_matches (tree))
|
||||
return TRUE;
|
||||
|
||||
for (prev = gtk_css_selector_tree_get_previous (tree);
|
||||
prev != NULL;
|
||||
prev = gtk_css_selector_tree_get_sibling (prev))
|
||||
{
|
||||
if (gtk_css_selector_tree_match_bloom (prev, filter, skipping))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const GtkCountingBloomFilter *filter;
|
||||
GPtrArray *results;
|
||||
} TreeMatchData;
|
||||
|
||||
static void
|
||||
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
||||
TreeMatchData *tm)
|
||||
{
|
||||
int i;
|
||||
gpointer *matches;
|
||||
|
||||
matches = gtk_css_selector_tree_get_matches (tree);
|
||||
if (matches)
|
||||
{
|
||||
if (tm->results == NULL)
|
||||
tm->results = g_ptr_array_sized_new (16);
|
||||
|
||||
for (i = 0; matches[i] != NULL; i++)
|
||||
g_ptr_array_insert_sorted (tm->results, matches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_selector_tree_match_foreach (const GtkCssSelector *selector,
|
||||
GtkCssNode *node,
|
||||
gpointer res)
|
||||
gpointer data)
|
||||
{
|
||||
TreeMatchData *tm = data;
|
||||
const GtkCssSelectorTree *tree = (const GtkCssSelectorTree *) selector;
|
||||
const GtkCssSelectorTree *prev;
|
||||
|
||||
if (!gtk_css_selector_match (selector, node))
|
||||
return FALSE;
|
||||
|
||||
gtk_css_selector_tree_found_match (tree, res);
|
||||
gtk_css_selector_tree_found_match (tree, tm);
|
||||
|
||||
if (tm->filter && !gtk_css_selector_is_simple (&tree->selector))
|
||||
{
|
||||
/* We can pass both TRUE or FALSE for skipping here, because the
|
||||
* function will immediately update it. */
|
||||
if (!gtk_css_selector_tree_match_bloom (tree, tm->filter, FALSE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (prev = gtk_css_selector_tree_get_previous (tree);
|
||||
prev != NULL;
|
||||
prev = gtk_css_selector_tree_get_sibling (prev))
|
||||
gtk_css_selector_foreach (&prev->selector, node, gtk_css_selector_tree_match_foreach, res);
|
||||
gtk_css_selector_foreach (&prev->selector, node, gtk_css_selector_tree_match_foreach, tm);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node)
|
||||
{
|
||||
GPtrArray *array = NULL;
|
||||
TreeMatchData tm = { filter, NULL };
|
||||
|
||||
for (; tree != NULL;
|
||||
tree = gtk_css_selector_tree_get_sibling (tree))
|
||||
gtk_css_selector_foreach (&tree->selector, node, gtk_css_selector_tree_match_foreach, &array);
|
||||
gtk_css_selector_foreach (&tree->selector, node, gtk_css_selector_tree_match_foreach, &tm);
|
||||
|
||||
return array;
|
||||
return tm.results;
|
||||
}
|
||||
|
||||
/* The code for collecting matches assumes that the name, id and classes
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef __GTK_CSS_SELECTOR_PRIVATE_H__
|
||||
#define __GTK_CSS_SELECTOR_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcountingbloomfilterprivate.h"
|
||||
#include "gtk/gtkcsstypesprivate.h"
|
||||
#include "gtk/gtkcssparserprivate.h"
|
||||
|
||||
@ -42,6 +43,7 @@ int _gtk_css_selector_compare (const GtkCssSelector *a,
|
||||
|
||||
void _gtk_css_selector_tree_free (GtkCssSelectorTree *tree);
|
||||
GPtrArray * _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node);
|
||||
GtkCssChange _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
GtkCssNode *node);
|
||||
|
@ -161,10 +161,12 @@ gtk_css_static_style_get_default (void)
|
||||
*/
|
||||
if (default_style == NULL)
|
||||
{
|
||||
GtkCountingBloomFilter filter = GTK_COUNTING_BLOOM_FILTER_INIT;
|
||||
GtkSettings *settings;
|
||||
|
||||
settings = gtk_settings_get_default ();
|
||||
default_style = gtk_css_static_style_new_compute (GTK_STYLE_PROVIDER (settings),
|
||||
&filter,
|
||||
NULL,
|
||||
0);
|
||||
g_object_set_data_full (G_OBJECT (settings), I_("gtk-default-style"),
|
||||
@ -176,6 +178,7 @@ gtk_css_static_style_get_default (void)
|
||||
|
||||
GtkCssStyle *
|
||||
gtk_css_static_style_new_compute (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssChange change)
|
||||
{
|
||||
@ -187,6 +190,7 @@ gtk_css_static_style_new_compute (GtkStyleProvider *provider,
|
||||
|
||||
if (node)
|
||||
gtk_style_provider_lookup (provider,
|
||||
filter,
|
||||
node,
|
||||
&lookup,
|
||||
change == 0 ? &change : NULL);
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include "gtk/gtkcssstyleprivate.h"
|
||||
|
||||
#include "gtk/gtkcountingbloomfilterprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_STATIC_STYLE (gtk_css_static_style_get_type ())
|
||||
@ -52,6 +54,7 @@ GType gtk_css_static_style_get_type (void) G_GNUC_CO
|
||||
|
||||
GtkCssStyle * gtk_css_static_style_get_default (void);
|
||||
GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssChange change);
|
||||
|
||||
|
@ -24,12 +24,13 @@ G_DEFINE_TYPE (GtkCssTransientNode, gtk_css_transient_node, GTK_TYPE_CSS_NODE)
|
||||
|
||||
static GtkCssStyle *
|
||||
gtk_css_transient_node_update_style (GtkCssNode *cssnode,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssChange change,
|
||||
gint64 timestamp,
|
||||
GtkCssStyle *style)
|
||||
{
|
||||
/* This should get rid of animations */
|
||||
return GTK_CSS_NODE_CLASS (gtk_css_transient_node_parent_class)->update_style (cssnode, change, 0, style);
|
||||
return GTK_CSS_NODE_CLASS (gtk_css_transient_node_parent_class)->update_style (cssnode, filter, change, 0, style);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -180,6 +180,7 @@ gtk_style_cascade_get_keyframes (GtkStyleProvider *provider,
|
||||
|
||||
static void
|
||||
gtk_style_cascade_lookup (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssLookup *lookup,
|
||||
GtkCssChange *change)
|
||||
@ -193,7 +194,7 @@ gtk_style_cascade_lookup (GtkStyleProvider *provider,
|
||||
item;
|
||||
item = gtk_style_cascade_iter_next (cascade, &iter))
|
||||
{
|
||||
gtk_style_provider_lookup (item, node, lookup,
|
||||
gtk_style_provider_lookup (item, filter, node, lookup,
|
||||
change ? &iter_change : NULL);
|
||||
if (change)
|
||||
*change |= iter_change;
|
||||
|
@ -93,6 +93,7 @@ gtk_style_provider_get_keyframes (GtkStyleProvider *provider,
|
||||
|
||||
void
|
||||
gtk_style_provider_lookup (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssLookup *lookup,
|
||||
GtkCssChange *out_change)
|
||||
@ -111,7 +112,7 @@ gtk_style_provider_lookup (GtkStyleProvider *provider,
|
||||
if (!iface->lookup)
|
||||
return;
|
||||
|
||||
iface->lookup (provider, node, lookup, out_change);
|
||||
iface->lookup (provider, filter, node, lookup, out_change);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define __GTK_STYLE_PROVIDER_PRIVATE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "gtk/gtkcountingbloomfilterprivate.h"
|
||||
#include "gtk/gtkcsskeyframesprivate.h"
|
||||
#include "gtk/gtkcsslookupprivate.h"
|
||||
#include "gtk/gtkcssnodeprivate.h"
|
||||
@ -42,6 +43,7 @@ struct _GtkStyleProviderInterface
|
||||
const char *name);
|
||||
int (* get_scale) (GtkStyleProvider *provider);
|
||||
void (* lookup) (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssLookup *lookup,
|
||||
GtkCssChange *out_change);
|
||||
@ -59,6 +61,7 @@ GtkCssKeyframes * gtk_style_provider_get_keyframes (GtkStyleProvid
|
||||
const char *name);
|
||||
int gtk_style_provider_get_scale (GtkStyleProvider *provider);
|
||||
void gtk_style_provider_lookup (GtkStyleProvider *provider,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkCssLookup *lookup,
|
||||
GtkCssChange *out_change);
|
||||
|
Loading…
Reference in New Issue
Block a user