Compare commits

...

17 Commits

Author SHA1 Message Date
Matthias Clasen
de0c61754e Dump lookup statistics
Print out numbers of lookups, their size, and
the amount of sharing.

For widget-factory, the numbers are like this:
319 different lookups, 890 total, 18.5022 avg length

For the gtk-demo listbox example, the number are:
58 different lookups, 9742 total, 15.9997 avg length
2020-05-17 23:24:32 -04:00
Matthias Clasen
21a4fd1a5f Make GtkCssLookupValue refcounted 2020-05-17 22:59:27 -04:00
Matthias Clasen
498f816f1f Keep an empty lookup singleton
This is a simple optimization to avoid wasting a good
chunk of memory (~16k in widget-factory) on identical
structures. This is the one case that it easy to handle.
2020-05-17 22:59:27 -04:00
Matthias Clasen
343c80a609 css style: Use a linear sweep to compute values
We can again take advantage of the lookup values
being sorted, and only iterate through them once
to find all the values for a given group.
2020-05-17 22:52:55 -04:00
Matthias Clasen
8a5bb6cb5f lookup: Merge rulesets more efficiently
Keep lookups sorted, and take advantage of the fact
that the rulesets are sorted, too. We can merge them
in a linear sweep.
2020-05-17 22:52:55 -04:00
Matthias Clasen
05376fca63 css provider: Keep rulesets sorted
Keep each ruleset sorted by property id. This
will let us be faster when adding the rules to
a lookup later on.
2020-05-17 22:52:55 -04:00
Matthias Clasen
a112c3ff45 Revamp lookup memory handling
Make GtkCssLookup keep an an array of pointers to the
PropertyValue structs in the rulesets, instead of copying
things. Then make GtkCssStaticStyle find sections in the
lookup, instead of keeping a separate array for those.
2020-05-17 22:52:55 -04:00
Matthias Clasen
91120d3f46 cssnode: Reused cached lookups
When we determine that the lookup won't change,
reuse the cached lookup by passing it to
to gtk_css_static_style_new_compute.
2020-05-17 22:52:55 -04:00
Matthias Clasen
37c299dfcb cssnode: Rearrange code a bit
Move all the cases of style updating into
gtk_css_node_create_style() and also fold
gtk_css_style_needs_recreation into this function.
2020-05-17 22:39:54 -04:00
Matthias Clasen
0c871dcab0 Pass a lookup to gtk_css_static_style_new_compute
Allow passing a lookup to gtk_css_static_style_new_compute
to bypass the matching and just resolve the style based
on that lookup.

Update all callers to pass NULL for now.
2020-05-17 22:39:45 -04:00
Matthias Clasen
fa79e131e0 style: Cache the lookup
This is not used for anything yet.
2020-05-17 22:30:09 -04:00
Matthias Clasen
e34d7d07b1 lookup: Don't store flat arrays
Most lookups have no or just a few values.
We can drastically reduce the amount of memory used for lookups,
and then we can afford to keep them around and avoid some lookups
in the future.
2020-05-17 22:30:09 -04:00
Matthias Clasen
6fb18b74b4 lookup: Add a getter
This will make it easier to change the internals
in the next commits.
2020-05-17 22:30:09 -04:00
Matthias Clasen
acb5c2abef Make lookups refcounted
This will be useful when we share lookups.
2020-05-17 22:30:09 -04:00
Matthias Clasen
bfa7f57a92 lookup: Loose the underscores
We are going to pretty much rewrite this in the
following commits. Take the opportunity to drop
the leading _ from the api.
2020-05-17 22:30:09 -04:00
Matthias Clasen
bbad192209 Clean up some includes
gtkcsslookupprivate.h does not need to include
gtkcssstaticstyleprivate.h. Fix up the fallout
in gtkcsswidgetnode.c.
2020-05-17 22:30:07 -04:00
Matthias Clasen
1401a69faf perf test: Discard invalid runs
It turns out that we occasionally get a 0, which we
should just ignore to avoid skewing the numbers.

Also add a --verbose option which dumps all values
and makes debugging this sort of issue easier.
2020-05-17 22:29:30 -04:00
8 changed files with 449 additions and 209 deletions

View File

@@ -24,53 +24,276 @@
#include "gtkprivatetypebuiltins.h"
#include "gtkprivate.h"
void
_gtk_css_lookup_init (GtkCssLookup *lookup)
GtkCssLookupValue *
gtk_css_lookup_value_new (guint id,
GtkCssValue *value,
GtkCssSection *section)
{
memset (lookup, 0, sizeof (*lookup));
GtkCssLookupValue *v;
v = g_new0 (GtkCssLookupValue, 1);
v->ref_count = 1;
v->id = id;
v->value = _gtk_css_value_ref (value);
if (section)
v->section = gtk_css_section_ref (section);
return v;
}
static void
gtk_css_lookup_value_free (GtkCssLookupValue *value)
{
_gtk_css_value_unref (value->value);
if (value->section)
gtk_css_section_unref (value->section);
g_free (value);
}
GtkCssLookupValue *
gtk_css_lookup_value_ref (GtkCssLookupValue *value)
{
value->ref_count++;
return value;
}
void
gtk_css_lookup_value_unref (GtkCssLookupValue *value)
{
value->ref_count--;
if (value->ref_count == 0)
gtk_css_lookup_value_free (value);
}
static GHashTable *lookups;
static gboolean
gtk_css_lookup_equal (gconstpointer p1,
gconstpointer p2)
{
const GtkCssLookup *l1 = p1;
const GtkCssLookup *l2 = p2;
int i;
if (!_gtk_bitmask_equals (l1->set_values, l2->set_values))
return FALSE;
if (l1->values == NULL && l2->values == NULL)
return TRUE;
if (l1->values == NULL || l2->values == NULL)
return FALSE;
if (l1->values->len != l2->values->len)
return FALSE;
for (i = 0; i < l1->values->len; i++)
{
GtkCssLookupValue *v1 = g_ptr_array_index (l1->values, i);
GtkCssLookupValue *v2 = g_ptr_array_index (l2->values, i);
if (!_gtk_css_value_equal (v1->value, v2->value))
return FALSE;
}
return TRUE;
}
static guint
gtk_css_lookup_hash (gconstpointer data)
{
const GtkCssLookup *l = data;
int i;
guint h;
if (l->values == NULL)
return 0;
h = 0;
for (i = 0; i < l->values->len; i++)
{
GtkCssLookupValue *v = g_ptr_array_index (l->values, i);
char *s = _gtk_css_value_to_string (v->value);
h += g_str_hash (s);
g_free (s);
}
return h;
}
static gboolean
dump_lookups (gpointer data)
{
GHashTableIter iter;
GtkCssLookup *key;
gpointer value;
int total = 0;
int length = 0;
g_hash_table_iter_init (&iter, lookups);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
total += GPOINTER_TO_INT (value);
length += GPOINTER_TO_INT (value) * key->values->len;
}
g_print ("lookup stats:\n");
g_print ("\t%d different lookups, %d total, %g avg length\n",
g_hash_table_size (lookups),
total,
length / (1.0 * total));
g_hash_table_iter_init (&iter, lookups);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
g_print ("\t%d\t%d\n", GPOINTER_TO_INT (value), key->values->len);
g_print ("\n");
return G_SOURCE_CONTINUE;
}
GtkCssLookup *
gtk_css_lookup_new (void)
{
GtkCssLookup *lookup = g_new0 (GtkCssLookup, 1);
lookup->ref_count = 1;
lookup->set_values = _gtk_bitmask_new ();
if (!lookups)
{
lookups = g_hash_table_new (gtk_css_lookup_hash, gtk_css_lookup_equal);
g_timeout_add (1000, dump_lookups, NULL);
}
return lookup;
}
void
_gtk_css_lookup_destroy (GtkCssLookup *lookup)
gtk_css_lookup_register (GtkCssLookup *lookup)
{
gint count;
count = GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup));
count++;
if (count == 1)
gtk_css_lookup_ref (lookup);
g_hash_table_insert (lookups, lookup, GINT_TO_POINTER (count));
}
static void
gtk_css_lookup_unregister (GtkCssLookup *lookup)
{
gint count;
count = GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup));
g_assert (count > 0);
if (count == 1)
g_hash_table_remove (lookups, lookup);
else
{
count--;
g_hash_table_insert (lookups, lookup, GINT_TO_POINTER (count));
}
}
static void
gtk_css_lookup_free (GtkCssLookup *lookup)
{
gtk_css_lookup_unregister (lookup);
_gtk_bitmask_free (lookup->set_values);
if (lookup->values)
g_ptr_array_unref (lookup->values);
g_free (lookup);
}
gboolean
_gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
guint id)
GtkCssLookup *
gtk_css_lookup_ref (GtkCssLookup *lookup)
{
gtk_internal_return_val_if_fail (lookup != NULL, FALSE);
gtk_internal_return_val_if_fail (lookup != NULL, NULL);
gtk_internal_return_val_if_fail (lookup->ref_count > 0, NULL);
return !_gtk_bitmask_get (lookup->set_values, id);
lookup->ref_count++;
return lookup;
}
/**
* _gtk_css_lookup_set:
* @lookup: the lookup
* @id: id of the property to set, see _gtk_style_property_get_id()
* @section: (allow-none): The @section the value was defined in or %NULL
* @value: the “cascading value” to use
*
* Sets the @value for a given @id. No value may have been set for @id
* before. See _gtk_css_lookup_is_missing(). This function is used to
* set the “winning declaration” of a lookup. Note that for performance
* reasons @value and @section are not copied. It is your responsibility
* to ensure they are kept alive until _gtk_css_lookup_free() is called.
**/
void
_gtk_css_lookup_set (GtkCssLookup *lookup,
guint id,
GtkCssSection *section,
GtkCssValue *value)
gtk_css_lookup_unref (GtkCssLookup *lookup)
{
gtk_internal_return_if_fail (lookup != NULL);
gtk_internal_return_if_fail (value != NULL);
gtk_internal_return_if_fail (lookup->values[id].value == NULL);
gtk_internal_return_if_fail (lookup->ref_count > 0);
lookup->values[id].value = value;
lookup->values[id].section = section;
lookup->set_values = _gtk_bitmask_set (lookup->set_values, id, TRUE);
lookup->ref_count--;
if (lookup->ref_count == 1 &&
GPOINTER_TO_INT (g_hash_table_lookup (lookups, lookup)) == 1)
lookup->ref_count--;
if (lookup->ref_count == 0)
gtk_css_lookup_free (lookup);
}
/*
* gtk_css_lookup_fill:
* @lookup: the #GtkCssLookup to populate
* @values: array of values to place into unpopulated slots in @lookup
* @n_values: the length of @values
*
* Add the @values to @lookup for properties for which
* @lookup does not have a value yet.
*/
void
gtk_css_lookup_fill (GtkCssLookup *lookup,
GtkCssLookupValue **values,
guint n_values)
{
int i, j;
gtk_internal_return_if_fail (lookup != NULL);
gtk_internal_return_if_fail (values != NULL);
if (!lookup->values)
lookup->values = g_ptr_array_new_full (MAX (16, n_values),
(GDestroyNotify)gtk_css_lookup_value_unref);
for (i = 0, j = 0; j < n_values; j++, i++)
{
GtkCssLookupValue *v = NULL;
for (; i < lookup->values->len; i++)
{
v = g_ptr_array_index (lookup->values, i);
if (v->id >= values[j]->id)
break;
}
if (i == lookup->values->len || v->id > values[j]->id)
{
g_ptr_array_insert (lookup->values, i, gtk_css_lookup_value_ref (values[j]));
lookup->set_values = _gtk_bitmask_set (lookup->set_values, values[j]->id, TRUE);
}
}
}
GtkCssSection *
gtk_css_lookup_get_section (GtkCssLookup *lookup,
guint id)
{
if (_gtk_bitmask_get (lookup->set_values, id))
{
int i;
for (i = 0; i < lookup->values->len; i++)
{
GtkCssLookupValue *value = g_ptr_array_index (lookup->values, i);
if (value->id == id)
return value->section;
}
}
return NULL;
}

View File

@@ -21,9 +21,9 @@
#include <glib-object.h>
#include "gtk/gtkbitmaskprivate.h"
#include "gtk/gtkcssstaticstyleprivate.h"
#include "gtk/css/gtkcsssection.h"
#include "gtk/gtkcssvalueprivate.h"
G_BEGIN_DECLS
@@ -31,30 +31,62 @@ G_BEGIN_DECLS
typedef struct _GtkCssLookup GtkCssLookup;
typedef struct {
GtkCssSection *section;
GtkCssValue *value;
int ref_count;
guint id;
GtkCssValue *value;
GtkCssSection *section;
} GtkCssLookupValue;
GtkCssLookupValue * gtk_css_lookup_value_new (guint id,
GtkCssValue *value,
GtkCssSection *section);
GtkCssLookupValue * gtk_css_lookup_value_ref (GtkCssLookupValue *value);
void gtk_css_lookup_value_unref (GtkCssLookupValue *value);
struct _GtkCssLookup {
int ref_count;
GtkBitmask *set_values;
GtkCssLookupValue values[GTK_CSS_PROPERTY_N_PROPERTIES];
GPtrArray *values;
};
void _gtk_css_lookup_init (GtkCssLookup *lookup);
void _gtk_css_lookup_destroy (GtkCssLookup *lookup);
gboolean _gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
GtkCssLookup * gtk_css_lookup_new (void);
GtkCssLookup * gtk_css_lookup_ref (GtkCssLookup *lookup);
void gtk_css_lookup_unref (GtkCssLookup *lookup);
void gtk_css_lookup_fill (GtkCssLookup *lookup,
GtkCssLookupValue **values,
guint n_values);
GtkCssSection * gtk_css_lookup_get_section (GtkCssLookup *lookup,
guint id);
void _gtk_css_lookup_set (GtkCssLookup *lookup,
guint id,
GtkCssSection *section,
GtkCssValue *value);
static inline const GtkBitmask *
_gtk_css_lookup_get_set_values (const GtkCssLookup *lookup)
gtk_css_lookup_get_set_values (const GtkCssLookup *lookup)
{
return lookup->set_values;
}
static inline GtkCssLookupValue *
gtk_css_lookup_get (GtkCssLookup *lookup,
guint id)
{
if (_gtk_bitmask_get (lookup->set_values, id))
{
int i;
for (i = 0; i < lookup->values->len; i++)
{
GtkCssLookupValue *value = g_ptr_array_index (lookup->values, i);
if (value->id == id)
return value;
}
}
return NULL;
}
void gtk_css_lookup_register (GtkCssLookup *lookup);
G_END_DECLS
#endif /* __GTK_CSS_LOOKUP_PRIVATE_H__ */

View File

@@ -356,64 +356,61 @@ store_in_global_parent_cache (GtkCssNode *node,
}
static GtkCssStyle *
gtk_css_node_create_style (GtkCssNode *cssnode,
const GtkCountingBloomFilter *filter,
GtkCssChange change)
compute_style (GtkStyleProvider *provider,
const GtkCountingBloomFilter *filter,
GtkCssNode *cssnode,
GtkCssLookup *lookup,
GtkCssChange change)
{
const GtkCssNodeDeclaration *decl;
GtkCssStyle *style;
GtkCssChange style_change;
decl = gtk_css_node_get_declaration (cssnode);
style = lookup_in_global_parent_cache (cssnode, decl);
if (style)
return g_object_ref (style);
created_styles++;
if (change & GTK_CSS_CHANGE_NEEDS_RECOMPUTE)
{
/* Need to recompute the change flags */
style_change = 0;
}
else
{
style_change = gtk_css_static_style_get_change (gtk_css_style_get_static_style (cssnode->style));
}
style = gtk_css_static_style_new_compute (gtk_css_node_get_style_provider (cssnode),
filter,
cssnode,
style_change);
style = gtk_css_static_style_new_compute (provider, filter, cssnode, lookup, change);
store_in_global_parent_cache (cssnode, decl, style);
return style;
}
static GtkCssStyle *
gtk_css_node_create_style (GtkCssNode *cssnode,
GtkCssStyle *style,
const GtkCountingBloomFilter *filter,
GtkCssChange change)
{
GtkCssStyle *new_style;
GtkCssChange style_change;
GtkCssLookup *lookup;
GtkStyleProvider *provider;
provider = gtk_css_node_get_style_provider (cssnode);
style_change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
lookup = gtk_css_static_style_get_lookup (GTK_CSS_STATIC_STYLE (style));
if (change & (GTK_CSS_RADICAL_CHANGE & ~GTK_CSS_CHANGE_PARENT_STYLE))
new_style = compute_style (provider, filter, cssnode, NULL, 0);
else if (change & style_change)
new_style = compute_style (provider, filter, cssnode, NULL, style_change);
else if (change & GTK_CSS_CHANGE_PARENT_STYLE)
new_style = compute_style (provider, filter, cssnode, lookup, style_change);
else
new_style = g_object_ref (style);
return new_style;
}
static gboolean
should_create_transitions (GtkCssChange change)
{
return (change & GTK_CSS_CHANGE_ANIMATIONS) == 0;
}
static gboolean
gtk_css_style_needs_recreation (GtkCssStyle *style,
GtkCssChange change)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_STATIC_STYLE (style), TRUE);
/* Try to avoid invalidating if we can */
if (change & GTK_CSS_RADICAL_CHANGE)
return TRUE;
if (gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style)) & change)
return TRUE;
else
return FALSE;
}
static GtkCssStyle *
gtk_css_node_real_update_style (GtkCssNode *cssnode,
const GtkCountingBloomFilter *filter,
@@ -425,10 +422,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, filter, change);
else
new_static_style = g_object_ref (static_style);
new_static_style = gtk_css_node_create_style (cssnode, static_style, filter, change);
if (new_static_style != static_style || (change & GTK_CSS_CHANGE_ANIMATIONS))
{

View File

@@ -86,23 +86,16 @@ struct _GtkCssProviderClass
typedef struct GtkCssRuleset GtkCssRuleset;
typedef struct _GtkCssScanner GtkCssScanner;
typedef struct _PropertyValue PropertyValue;
typedef enum ParserScope ParserScope;
typedef enum ParserSymbol ParserSymbol;
struct _PropertyValue {
GtkCssStyleProperty *property;
GtkCssValue *value;
GtkCssSection *section;
};
struct GtkCssRuleset
{
GtkCssSelector *selector;
GtkCssSelectorTree *selector_match;
PropertyValue *styles;
GtkCssLookupValue **styles;
guint n_styles;
guint owns_styles : 1;
};
struct _GtkCssScanner
@@ -231,30 +224,23 @@ gtk_css_ruleset_init_copy (GtkCssRuleset *new,
GtkCssRuleset *ruleset,
GtkCssSelector *selector)
{
int i;
memcpy (new, ruleset, sizeof (GtkCssRuleset));
new->selector = selector;
/* First copy takes over ownership */
if (ruleset->owns_styles)
ruleset->owns_styles = FALSE;
for (i = 0; i < new->n_styles; i++)
gtk_css_lookup_value_ref (new->styles[i]);
}
static void
gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
{
if (ruleset->owns_styles)
{
guint i;
int i;
for (i = 0; i < ruleset->n_styles; i++)
gtk_css_lookup_value_unref (ruleset->styles[i]);
for (i = 0; i < ruleset->n_styles; i++)
{
_gtk_css_value_unref (ruleset->styles[i].value);
ruleset->styles[i].value = NULL;
if (ruleset->styles[i].section)
gtk_css_section_unref (ruleset->styles[i].section);
}
g_free (ruleset->styles);
}
if (ruleset->selector)
_gtk_css_selector_free (ruleset->selector);
@@ -268,35 +254,30 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
GtkCssSection *section)
{
guint i;
guint id;
g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0);
ruleset->owns_styles = TRUE;
id = _gtk_css_style_property_get_id (property);
for (i = 0; i < ruleset->n_styles; i++)
{
if (ruleset->styles[i].property == property)
if (ruleset->styles[i]->id > id)
break;
if (ruleset->styles[i]->id == id)
{
_gtk_css_value_unref (ruleset->styles[i].value);
ruleset->styles[i].value = NULL;
if (ruleset->styles[i].section)
gtk_css_section_unref (ruleset->styles[i].section);
break;
gtk_css_lookup_value_unref (ruleset->styles[i]);
ruleset->styles[i] = gtk_css_lookup_value_new (id, value, section);
return;
}
}
if (i == ruleset->n_styles)
{
ruleset->n_styles++;
ruleset->styles = g_realloc (ruleset->styles, ruleset->n_styles * sizeof (PropertyValue));
ruleset->styles[i].value = NULL;
ruleset->styles[i].property = property;
}
ruleset->styles[i].value = value;
if (gtk_keep_css_sections)
ruleset->styles[i].section = gtk_css_section_ref (section);
else
ruleset->styles[i].section = NULL;
ruleset->styles = g_realloc (ruleset->styles, (ruleset->n_styles + 1) * sizeof (GtkCssLookupValue *));
if (i < ruleset->n_styles)
memmove (&ruleset->styles[i + 1], &ruleset->styles[i], (ruleset->n_styles - i) * sizeof (GtkCssLookupValue *));
ruleset->n_styles++;
ruleset->styles[i] = gtk_css_lookup_value_new (id, value, section);
}
static void
@@ -457,7 +438,6 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
GtkCssProvider *css_provider = GTK_CSS_PROVIDER (provider);
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
GtkCssRuleset *ruleset;
guint j;
int i;
GtkArray tree_rules_array;
GtkCssRuleset *rules_stack[32];
@@ -479,19 +459,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
if (ruleset->styles == NULL)
continue;
for (j = 0; j < ruleset->n_styles; j++)
{
GtkCssStyleProperty *prop = ruleset->styles[j].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,
ruleset->styles[j].section,
ruleset->styles[j].value);
}
gtk_css_lookup_fill (lookup, ruleset->styles, ruleset->n_styles);
}
gtk_array_free (&tree_rules_array, NULL);
@@ -1398,10 +1366,10 @@ compare_properties (gconstpointer a, gconstpointer b, gpointer style)
{
const guint *ua = a;
const guint *ub = b;
PropertyValue *styles = style;
GtkCssLookupValue **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)));
return strcmp (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ua]->id))),
_gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ub]->id))));
}
static void
@@ -1426,9 +1394,9 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
for (i = 0; i < ruleset->n_styles; i++)
{
PropertyValue *prop = &ruleset->styles[sorted[i]];
GtkCssLookupValue *prop = ruleset->styles[sorted[i]];
g_string_append (str, " ");
g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop->property)));
g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (prop->id))));
g_string_append (str, ": ");
_gtk_css_value_print (prop->value, str);
g_string_append (str, ";\n");

View File

@@ -43,8 +43,7 @@ static void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
guint id,
GtkCssValue *specified,
GtkCssSection *section);
GtkCssValue *specified);
static const int core_props[] = {
GTK_CSS_PROPERTY_COLOR,
@@ -199,19 +198,34 @@ gtk_css_ ## NAME ## _values_new_compute (GtkCssStaticStyle *sstyle, \
GtkCssLookup *lookup) \
{ \
GtkCssStyle *style = (GtkCssStyle *)sstyle; \
int i; \
int i, j; \
int n; \
\
style->NAME = (GtkCss ## TYPE ## Values *)gtk_css_values_new (GTK_CSS_ ## ENUM ## _VALUES); \
\
n = lookup->values ? lookup->values->len : 0; \
j = 0; \
for (i = 0; i < G_N_ELEMENTS (NAME ## _props); i++) \
{ \
guint id = NAME ## _props[i]; \
GtkCssValue *value = NULL; \
for (; j < n; j++) \
{ \
GtkCssLookupValue *v = g_ptr_array_index (lookup->values, j); \
if (v->id > id) \
break; \
if (v->id == id) \
{ \
value = v->value; \
break; \
} \
} \
\
gtk_css_static_style_compute_value (sstyle, \
provider, \
parent_style, \
id, \
lookup->values[id].value, \
lookup->values[id].section); \
value); \
} \
} \
static GtkBitmask * gtk_css_ ## NAME ## _values_mask; \
@@ -236,7 +250,7 @@ gtk_css_ ## NAME ## _values_init (void) \
static inline gboolean \
gtk_css_ ## NAME ## _values_unset (const GtkCssLookup *lookup) \
{ \
const GtkBitmask *set_values = _gtk_css_lookup_get_set_values (lookup); \
const GtkBitmask *set_values = gtk_css_lookup_get_set_values (lookup); \
return !_gtk_bitmask_intersects (set_values, gtk_css_ ## NAME ## _values_mask); \
}
@@ -298,15 +312,11 @@ G_DEFINE_TYPE (GtkCssStaticStyle, gtk_css_static_style, GTK_TYPE_CSS_STYLE)
static GtkCssSection *
gtk_css_static_style_get_section (GtkCssStyle *style,
guint id)
guint id)
{
GtkCssStaticStyle *sstyle = GTK_CSS_STATIC_STYLE (style);
if (sstyle->sections == NULL ||
id >= sstyle->sections->len)
return NULL;
return g_ptr_array_index (sstyle->sections, id);
return gtk_css_lookup_get_section (sstyle->lookup, id);
}
static void
@@ -314,11 +324,7 @@ gtk_css_static_style_dispose (GObject *object)
{
GtkCssStaticStyle *style = GTK_CSS_STATIC_STYLE (object);
if (style->sections)
{
g_ptr_array_unref (style->sections);
style->sections = NULL;
}
g_clear_pointer (&style->lookup, gtk_css_lookup_unref);
G_OBJECT_CLASS (gtk_css_static_style_parent_class)->dispose (object);
}
@@ -329,6 +335,8 @@ gtk_css_static_style_get_static_style (GtkCssStyle *style)
return (GtkCssStaticStyle *)style;
}
static GtkCssLookup *the_empty_lookup;
static void
gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass)
{
@@ -353,6 +361,8 @@ gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass)
gtk_css_other_values_init ();
verify_style_groups ();
the_empty_lookup = gtk_css_lookup_new ();
}
static void
@@ -360,13 +370,6 @@ gtk_css_static_style_init (GtkCssStaticStyle *style)
{
}
static void
maybe_unref_section (gpointer section)
{
if (section)
gtk_css_section_unref (section);
}
static inline void
gtk_css_take_value (GtkCssValue **variable,
GtkCssValue *value)
@@ -379,8 +382,7 @@ gtk_css_take_value (GtkCssValue **variable,
static void
gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle,
guint id,
GtkCssValue *value,
GtkCssSection *section)
GtkCssValue *value)
{
GtkCssStyle *style = (GtkCssStyle *)sstyle;
@@ -658,21 +660,6 @@ gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle,
g_assert_not_reached ();
break;
}
if (sstyle->sections && sstyle->sections->len > id && g_ptr_array_index (sstyle->sections, id))
{
gtk_css_section_unref (g_ptr_array_index (sstyle->sections, id));
g_ptr_array_index (sstyle->sections, id) = NULL;
}
if (section)
{
if (sstyle->sections == NULL)
sstyle->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
if (sstyle->sections->len <= id)
g_ptr_array_set_size (sstyle->sections, id + 1);
g_ptr_array_index (sstyle->sections, id) = gtk_css_section_ref (section);
}
}
static GtkCssStyle *default_style;
@@ -700,6 +687,7 @@ gtk_css_static_style_get_default (void)
default_style = gtk_css_static_style_new_compute (GTK_STYLE_PROVIDER (settings),
&filter,
NULL,
NULL,
0);
g_object_set_data_full (G_OBJECT (settings), I_("gtk-default-style"),
default_style, clear_default_style);
@@ -899,7 +887,7 @@ gtk_css_lookup_resolve (GtkCssLookup *lookup,
gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_set_values (lookup)))
if (_gtk_bitmask_is_empty (gtk_css_lookup_get_set_values (lookup)))
{
style->background = (GtkCssBackgroundValues *)gtk_css_values_ref (gtk_css_background_initial_values);
style->border = (GtkCssBorderValues *)gtk_css_values_ref (gtk_css_border_initial_values);
@@ -986,23 +974,38 @@ GtkCssStyle *
gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCountingBloomFilter *filter,
GtkCssNode *node,
GtkCssLookup *lookup,
GtkCssChange change)
{
GtkCssStaticStyle *result;
GtkCssLookup lookup;
GtkCssNode *parent;
_gtk_css_lookup_init (&lookup);
if (node)
gtk_style_provider_lookup (provider,
filter,
node,
&lookup,
change == 0 ? &change : NULL);
result = g_object_new (GTK_TYPE_CSS_STATIC_STYLE, NULL);
if (lookup != NULL && change != 0)
{
gtk_css_lookup_ref (lookup);
}
else
{
lookup = gtk_css_lookup_new ();
if (node)
gtk_style_provider_lookup (provider,
filter,
node,
lookup,
change == 0 ? &change : NULL);
gtk_css_lookup_register (lookup);
if (_gtk_bitmask_is_empty (gtk_css_lookup_get_set_values (lookup)))
{
gtk_css_lookup_unref (lookup);
lookup = gtk_css_lookup_ref (the_empty_lookup);
}
}
result->lookup = lookup;
result->change = change;
if (node)
@@ -1010,13 +1013,11 @@ gtk_css_static_style_new_compute (GtkStyleProvider *provider,
else
parent = NULL;
gtk_css_lookup_resolve (&lookup,
gtk_css_lookup_resolve (lookup,
provider,
result,
parent ? gtk_css_node_get_style (parent) : NULL);
_gtk_css_lookup_destroy (&lookup);
return GTK_CSS_STYLE (result);
}
@@ -1031,8 +1032,7 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
guint id,
GtkCssValue *specified,
GtkCssSection *section)
GtkCssValue *specified)
{
GtkCssValue *value;
GtkBorderStyle border_style;
@@ -1055,7 +1055,7 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value ((GtkCssStyle *)style, id - 1));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
{
gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), section);
gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER));
return;
}
break;
@@ -1084,7 +1084,7 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
value = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style);
}
gtk_css_static_style_set_value (style, id, value, section);
gtk_css_static_style_set_value (style, id, value);
}
GtkCssChange
@@ -1094,3 +1094,11 @@ gtk_css_static_style_get_change (GtkCssStaticStyle *style)
return style->change;
}
GtkCssLookup *
gtk_css_static_style_get_lookup (GtkCssStaticStyle *style)
{
g_return_val_if_fail (GTK_IS_CSS_STATIC_STYLE (style), NULL);
return style->lookup;
}

View File

@@ -23,6 +23,7 @@
#include "gtk/gtkcssstyleprivate.h"
#include "gtk/gtkcountingbloomfilterprivate.h"
#include "gtk/gtkcsslookupprivate.h"
G_BEGIN_DECLS
@@ -40,9 +41,8 @@ struct _GtkCssStaticStyle
{
GtkCssStyle parent;
GPtrArray *sections; /* sections the values are defined in */
GtkCssChange change; /* change as returned by value lookup */
GtkCssChange change; /* change as returned by value lookup */
GtkCssLookup *lookup;
};
struct _GtkCssStaticStyleClass
@@ -56,8 +56,10 @@ GtkCssStyle * gtk_css_static_style_get_default (void);
GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCountingBloomFilter *filter,
GtkCssNode *node,
GtkCssLookup *lookup,
GtkCssChange change);
GtkCssChange gtk_css_static_style_get_change (GtkCssStaticStyle *style);
GtkCssLookup * gtk_css_static_style_get_lookup (GtkCssStaticStyle *style);
G_END_DECLS

View File

@@ -25,6 +25,7 @@
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
#include "gtkcssstaticstyleprivate.h"
G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)

View File

@@ -46,6 +46,7 @@ static char *opt_detail;
static char *opt_name;
static char *opt_output;
static gboolean opt_start_time;
static gboolean opt_verbose;
static GOptionEntry options[] = {
{ "mark", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_mark, "Name of the mark", "NAME" },
@@ -54,6 +55,7 @@ static GOptionEntry options[] = {
{ "runs", '0', G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &opt_rep, "Number of runs", "COUNT" },
{ "name", '0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_name, "Name of this test", "NAME" },
{ "output", '0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_output, "Directory to save syscap files", "DIRECTORY" },
{ "verbose", '0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_verbose, "Verbose output", NULL },
{ NULL, }
};
@@ -204,6 +206,9 @@ main (int argc, char *argv[])
/* Ignore the first run, to avoid cache effects */
for (i = 1; i < opt_rep; i++)
{
if (values[i] == 0)
continue;
if (min > values[i])
min = values[i];
if (max < values[i])
@@ -212,7 +217,14 @@ main (int argc, char *argv[])
total += values[i];
}
g_print ("%d runs, min %g, max %g, avg %g\n",
if (opt_verbose)
{
for (i = 1; i < opt_rep; i++)
g_print ("%g ", MILLISECONDS (values[i]));
g_print ("\n");
}
g_print ("%d runs counted, min %g, max %g, avg %g\n",
count,
MILLISECONDS (min),
MILLISECONDS (max),