summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtkcssanimatedstyle.c599
-rw-r--r--gtk/gtkcssanimatedstyleprivate.h90
-rw-r--r--gtk/gtkcssanimation.c6
-rw-r--r--gtk/gtkcsslookup.c22
-rw-r--r--gtk/gtkcsslookupprivate.h6
-rw-r--r--gtk/gtkcssstyle.c538
-rw-r--r--gtk/gtkcssstyleprivate.h53
-rw-r--r--gtk/gtkcsstransition.c10
-rw-r--r--gtk/gtkstyleanimation.c8
-rw-r--r--gtk/gtkstyleanimationprivate.h7
-rw-r--r--gtk/gtkstylecontext.c28
12 files changed, 767 insertions, 602 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index d2ffbd885c..0573e3e378 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -368,6 +368,7 @@ gtk_private_h_sources = \
gtkcomboboxprivate.h \
gtkcontainerprivate.h \
gtkcssanimationprivate.h \
+ gtkcssanimatedstyleprivate.h \
gtkcssarrayvalueprivate.h \
gtkcssbgsizevalueprivate.h \
gtkcssbordervalueprivate.h \
@@ -592,6 +593,7 @@ gtk_base_c_sources = \
gtkcomboboxtext.c \
gtkcontainer.c \
gtkcssanimation.c \
+ gtkcssanimatedstyle.c \
gtkcssarrayvalue.c \
gtkcssbgsizevalue.c \
gtkcssbordervalue.c \
diff --git a/gtk/gtkcssanimatedstyle.c b/gtk/gtkcssanimatedstyle.c
new file mode 100644
index 0000000000..4ced8d1e5d
--- /dev/null
+++ b/gtk/gtkcssanimatedstyle.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2012 Red Hat Inc.
+ *
+ * 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>
+ */
+
+#include "config.h"
+
+#include "gtkcssanimatedstyleprivate.h"
+
+#include "gtkcssanimationprivate.h"
+#include "gtkcssarrayvalueprivate.h"
+#include "gtkcssenumvalueprivate.h"
+#include "gtkcssinheritvalueprivate.h"
+#include "gtkcssinitialvalueprivate.h"
+#include "gtkcssnumbervalueprivate.h"
+#include "gtkcsssectionprivate.h"
+#include "gtkcssshorthandpropertyprivate.h"
+#include "gtkcssstringvalueprivate.h"
+#include "gtkcssstylepropertyprivate.h"
+#include "gtkcsstransitionprivate.h"
+#include "gtkprivate.h"
+#include "gtkstyleanimationprivate.h"
+#include "gtkstylepropertyprivate.h"
+#include "gtkstyleproviderprivate.h"
+
+G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE)
+
+static GtkCssValue *
+gtk_css_animated_style_get_value (GtkCssStyle *style,
+ guint id)
+{
+ GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+
+ if (animated->animated_values &&
+ id < animated->animated_values->len &&
+ g_ptr_array_index (animated->animated_values, id))
+ return g_ptr_array_index (animated->animated_values, id);
+
+ return gtk_css_animated_style_get_intrinsic_value (animated, id);
+}
+
+static GtkCssSection *
+gtk_css_animated_style_get_section (GtkCssStyle *style,
+ guint id)
+{
+ GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+
+ if (animated->sections == NULL ||
+ id >= animated->sections->len)
+ return NULL;
+
+ return g_ptr_array_index (animated->sections, id);
+}
+
+static GtkBitmask *
+gtk_css_animated_style_compute_dependencies (GtkCssStyle *style,
+ const GtkBitmask *parent_changes)
+{
+ GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+ GtkBitmask *changes;
+
+ changes = _gtk_bitmask_copy (parent_changes);
+ changes = _gtk_bitmask_intersect (changes, animated->depends_on_parent);
+ if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
+ changes = _gtk_bitmask_union (changes, animated->depends_on_color);
+ if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
+ changes = _gtk_bitmask_union (changes, animated->depends_on_font_size);
+
+ return changes;
+}
+
+static void
+gtk_css_animated_style_dispose (GObject *object)
+{
+ GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
+
+ if (style->values)
+ {
+ g_ptr_array_unref (style->values);
+ style->values = NULL;
+ }
+ if (style->sections)
+ {
+ g_ptr_array_unref (style->sections);
+ style->sections = NULL;
+ }
+ if (style->animated_values)
+ {
+ g_ptr_array_unref (style->animated_values);
+ style->animated_values = NULL;
+ }
+
+ g_slist_free_full (style->animations, g_object_unref);
+ style->animations = NULL;
+
+ G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->dispose (object);
+}
+
+static void
+gtk_css_animated_style_finalize (GObject *object)
+{
+ GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
+
+ _gtk_bitmask_free (style->depends_on_parent);
+ _gtk_bitmask_free (style->equals_parent);
+ _gtk_bitmask_free (style->depends_on_color);
+ _gtk_bitmask_free (style->depends_on_font_size);
+
+ G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->finalize (object);
+}
+
+static void
+gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkCssStyleClass *style_class = GTK_CSS_STYLE_CLASS (klass);
+
+ object_class->dispose = gtk_css_animated_style_dispose;
+ object_class->finalize = gtk_css_animated_style_finalize;
+
+ style_class->get_value = gtk_css_animated_style_get_value;
+ style_class->get_section = gtk_css_animated_style_get_section;
+ style_class->compute_dependencies = gtk_css_animated_style_compute_dependencies;
+}
+
+static void
+gtk_css_animated_style_init (GtkCssAnimatedStyle *style)
+{
+ style->depends_on_parent = _gtk_bitmask_new ();
+ style->equals_parent = _gtk_bitmask_new ();
+ style->depends_on_color = _gtk_bitmask_new ();
+ style->depends_on_font_size = _gtk_bitmask_new ();
+}
+
+GtkCssStyle *
+gtk_css_animated_style_new (void)
+{
+ return g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
+}
+
+static void
+maybe_unref_section (gpointer section)
+{
+ if (section)
+ gtk_css_section_unref (section);
+}
+
+void
+gtk_css_animated_style_compute_value (GtkCssAnimatedStyle *style,
+ GtkStyleProviderPrivate *provider,
+ int scale,
+ GtkCssStyle *parent_style,
+ guint id,
+ GtkCssValue *specified,
+ GtkCssSection *section)
+{
+ GtkCssDependencies dependencies;
+ GtkCssValue *value;
+
+ gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+ gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
+ gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
+
+ /* http://www.w3.org/TR/css3-cascade/#cascade
+ * Then, for every element, the value for each property can be found
+ * by following this pseudo-algorithm:
+ * 1) Identify all declarations that apply to the element
+ */
+ if (specified == NULL)
+ {
+ GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (id);
+
+ if (_gtk_css_style_property_is_inherit (prop))
+ specified = _gtk_css_inherit_value_new ();
+ else
+ specified = _gtk_css_initial_value_new ();
+ }
+ else
+ _gtk_css_value_ref (specified);
+
+ value = _gtk_css_value_compute (specified, id, provider, scale, GTK_CSS_STYLE (style), parent_style, &dependencies);
+
+ if (style->values == NULL)
+ style->values = g_ptr_array_new_full (_gtk_css_style_property_get_n_properties (),
+ (GDestroyNotify)_gtk_css_value_unref);
+ if (id >= style->values->len)
+ g_ptr_array_set_size (style->values, id + 1);
+
+ if (g_ptr_array_index (style->values, id))
+ _gtk_css_value_unref (g_ptr_array_index (style->values, id));
+ g_ptr_array_index (style->values, id) = _gtk_css_value_ref (value);
+
+ if (dependencies & (GTK_CSS_DEPENDS_ON_PARENT | GTK_CSS_EQUALS_PARENT))
+ style->depends_on_parent = _gtk_bitmask_set (style->depends_on_parent, id, TRUE);
+ if (dependencies & (GTK_CSS_EQUALS_PARENT))
+ style->equals_parent = _gtk_bitmask_set (style->equals_parent, id, TRUE);
+ if (dependencies & (GTK_CSS_DEPENDS_ON_COLOR))
+ style->depends_on_color = _gtk_bitmask_set (style->depends_on_color, id, TRUE);
+ if (dependencies & (GTK_CSS_DEPENDS_ON_FONT_SIZE))
+ style->depends_on_font_size = _gtk_bitmask_set (style->depends_on_font_size, id, TRUE);
+
+ if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
+ {
+ gtk_css_section_unref (g_ptr_array_index (style->sections, id));
+ g_ptr_array_index (style->sections, id) = NULL;
+ }
+
+ if (section)
+ {
+ if (style->sections == NULL)
+ style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
+ if (style->sections->len <= id)
+ g_ptr_array_set_size (style->sections, id + 1);
+
+ g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
+ }
+
+ _gtk_css_value_unref (value);
+ _gtk_css_value_unref (specified);
+}
+
+void
+gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *style,
+ guint id,
+ GtkCssValue *value)
+{
+ gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+ gtk_internal_return_if_fail (value != NULL);
+
+ if (style->animated_values == NULL)
+ style->animated_values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
+ if (id >= style->animated_values->len)
+ g_ptr_array_set_size (style->animated_values, id + 1);
+
+ if (g_ptr_array_index (style->animated_values, id))
+ _gtk_css_value_unref (g_ptr_array_index (style->animated_values, id));
+ g_ptr_array_index (style->animated_values, id) = _gtk_css_value_ref (value);
+
+}
+
+GtkCssValue *
+gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
+ guint id)
+{
+ gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
+
+ if (style->values == NULL ||
+ id >= style->values->len)
+ return NULL;
+
+ return g_ptr_array_index (style->values, id);
+}
+
+/* TRANSITIONS */
+
+typedef struct _TransitionInfo TransitionInfo;
+struct _TransitionInfo {
+ guint index; /* index into value arrays */
+ gboolean pending; /* TRUE if we still need to handle it */
+};
+
+static void
+transition_info_add (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES],
+ GtkStyleProperty *property,
+ guint index)
+{
+ if (property == NULL)
+ {
+ guint i;
+
+ for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
+ {
+ GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
+
+ transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
+ }
+ }
+ else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
+ {
+ GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
+ guint i;
+
+ for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
+ {
+ GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
+
+ transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
+ }
+ }
+ else if (GTK_IS_CSS_STYLE_PROPERTY (property))
+ {
+ guint id;
+
+ if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property)))
+ return;
+
+ id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property));
+ g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES);
+ infos[id].index = index;
+ infos[id].pending = TRUE;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+}
+
+static void
+transition_infos_set (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES],
+ GtkCssValue *transitions)
+{
+ guint i;
+
+ for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++)
+ {
+ GtkStyleProperty *property;
+ GtkCssValue *prop_value;
+
+ prop_value = _gtk_css_array_value_get_nth (transitions, i);
+ if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0)
+ property = NULL;
+ else
+ {
+ property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value));
+ if (property == NULL)
+ continue;
+ }
+
+ transition_info_add (infos, property, i);
+ }
+}
+
+static GtkStyleAnimation *
+gtk_css_animated_style_find_transition (GtkCssAnimatedStyle *style,
+ guint property_id)
+{
+ GSList *list;
+
+ for (list = style->animations; list; list = list->next)
+ {
+ if (!GTK_IS_CSS_TRANSITION (list->data))
+ continue;
+
+ if (_gtk_css_transition_get_property (list->data) == property_id)
+ return list->data;
+ }
+
+ return NULL;
+}
+
+static void
+gtk_css_animated_style_create_css_transitions (GtkCssAnimatedStyle *style,
+ gint64 timestamp,
+ GtkCssAnimatedStyle *source)
+{
+ TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
+ GtkCssValue *durations, *delays, *timing_functions;
+ guint i;
+
+ transition_infos_set (transitions, gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_PROPERTY));
+
+ durations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_DURATION);
+ delays = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_DELAY);
+ timing_functions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);
+
+ for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
+ {
+ GtkStyleAnimation *animation;
+ GtkCssValue *start, *end;
+ double duration, delay;
+
+ if (!transitions[i].pending)
+ continue;
+
+ duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
+ delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
+ if (duration + delay == 0.0)
+ continue;
+
+ start = gtk_css_animated_style_get_intrinsic_value (source, i);
+ end = gtk_css_animated_style_get_intrinsic_value (style, i);
+ if (_gtk_css_value_equal (start, end))
+ {
+ animation = gtk_css_animated_style_find_transition (GTK_CSS_ANIMATED_STYLE (source), i);
+ if (animation)
+ style->animations = g_slist_prepend (style->animations, g_object_ref (animation));
+ }
+ else
+ {
+ animation = _gtk_css_transition_new (i,
+ gtk_css_style_get_value (GTK_CSS_STYLE (source), i),
+ _gtk_css_array_value_get_nth (timing_functions, i),
+ timestamp + delay * G_USEC_PER_SEC,
+ timestamp + (delay + duration) * G_USEC_PER_SEC);
+ style->animations = g_slist_prepend (style->animations, animation);
+ }
+ }
+}
+
+static GtkStyleAnimation *
+gtk_css_animated_style_find_animation (GtkCssAnimatedStyle *style,
+ const char *name)
+{
+ GSList *list;
+
+ for (list = style->animations; list; list = list->next)
+ {
+ if (!GTK_IS_CSS_ANIMATION (list->data))
+ continue;
+
+ if (g_str_equal (_gtk_css_animation_get_name (list->data), name))
+ return list->data;
+ }
+
+ return NULL;
+}
+
+static void
+gtk_css_animated_style_create_css_animations (GtkCssAnimatedStyle *style,
+ GtkCssAnimatedStyle *parent_style,
+ gint64 timestamp,
+ GtkStyleProviderPrivate *provider,
+ int scale,
+ GtkCssAnimatedStyle *source)
+{
+ GtkCssValue *durations, *delays, *timing_functions, *animations;
+ GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
+ guint i;
+
+ animations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_NAME);
+ durations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DURATION);
+ delays = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DELAY);
+ timing_functions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
+ iteration_counts = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
+ directions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
+ play_states = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
+ fill_modes = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);
+
+ for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
+ {
+ GtkStyleAnimation *animation;
+ GtkCssKeyframes *keyframes;
+ const char *name;
+
+ name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
+ if (g_ascii_strcasecmp (name, "none") == 0)
+ continue;
+
+ animation = gtk_css_animated_style_find_animation (style, name);
+ if (animation)
+ continue;
+
+ if (source)
+ animation = gtk_css_animated_style_find_animation (source, name);
+
+ if (animation)
+ {
+ animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
+ timestamp,
+ _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
+ }
+ else
+ {
+ keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
+ if (keyframes == NULL)
+ continue;
+
+ keyframes = _gtk_css_keyframes_compute (keyframes, provider, scale, GTK_CSS_STYLE (style), GTK_CSS_STYLE (parent_style));
+
+ animation = _gtk_css_animation_new (name,
+ keyframes,
+ timestamp,
+ _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
+ _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
+ _gtk_css_array_value_get_nth (timing_functions, i),
+ _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
+ _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
+ _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
+ _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
+ _gtk_css_keyframes_unref (keyframes);
+ }
+ style->animations = g_slist_prepend (style->animations, animation);
+ }
+}
+
+/* PUBLIC API */
+
+void
+gtk_css_animated_style_create_animations (GtkCssAnimatedStyle *style,
+ GtkCssAnimatedStyle *parent_style,
+ gint64 timestamp,
+ GtkStyleProviderPrivate *provider,
+ int scale,
+ GtkCssAnimatedStyle *source)
+{
+ if (source != NULL)
+ gtk_css_animated_style_create_css_transitions (style, timestamp, source);
+ gtk_css_animated_style_create_css_animations (style, parent_style, timestamp, provider, scale, source);
+}
+
+GtkBitmask *
+gtk_css_animated_style_advance (GtkCssAnimatedStyle *style,
+ gint64 timestamp)
+{
+ GtkBitmask *changed;
+ GPtrArray *old_computed_values;
+ GSList *list;
+ guint i;
+
+ gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
+ gtk_internal_return_val_if_fail (timestamp >= style->current_time, NULL);
+
+ style->current_time = timestamp;
+ old_computed_values = style->animated_values;
+ style->animated_values = NULL;
+
+ list = style->animations;
+ while (list)
+ {
+ GtkStyleAnimation *animation = list->data;
+
+ list = list->next;
+
+ _gtk_style_animation_set_values (animation,
+ timestamp,
+ GTK_CSS_ANIMATED_STYLE (style));
+
+ if (_gtk_style_animation_is_finished (animation, timestamp))
+ {
+ style->animations = g_slist_remove (style->animations, animation);
+ g_object_unref (animation);
+ }
+ }
+
+ /* figure out changes */
+ changed = _gtk_bitmask_new ();
+
+ for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
+ {
+ GtkCssValue *old_animated, *new_animated;
+
+ old_animated = old_computed_values && i < old_computed_values->len ? g_ptr_array_index (old_computed_values, i) : NULL;
+ new_animated = style->animated_values && i < style->animated_values->len ? g_ptr_array_index (style->animated_values, i) : NULL;
+
+ if (!_gtk_css_value_equal0 (old_animated, new_animated))
+ changed = _gtk_bitmask_set (changed, i, TRUE);
+ }
+
+ if (old_computed_values)
+ g_ptr_array_unref (old_computed_values);
+
+ return changed;
+}
+
+gboolean
+gtk_css_animated_style_is_static (GtkCssAnimatedStyle *style)
+{
+ GSList *list;
+
+ gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), TRUE);
+
+ for (list = style->animations; list; list = list->next)
+ {
+ if (!_gtk_style_animation_is_static (list->data, style->current_time))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+gtk_css_animated_style_cancel_animations (GtkCssAnimatedStyle *style)
+{
+ gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+
+ if (style->animated_values)
+ {
+ g_ptr_array_unref (style->animated_values);
+ style->animated_values = NULL;
+ }
+
+ g_slist_free_full (style->animations, g_object_unref);
+ style->animations = NULL;
+}
+
diff --git a/gtk/gtkcssanimatedstyleprivate.h b/gtk/gtkcssanimatedstyleprivate.h
new file mode 100644
index 0000000000..07b094b2ea
--- /dev/null
+++ b/gtk/gtkcssanimatedstyleprivate.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2012 Red Hat Inc.
+ *
+ * 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_CSS_ANIMATED_STYLE_PRIVATE_H__
+#define __GTK_CSS_ANIMATED_STYLE_PRIVATE_H__
+
+#include "gtk/gtkcssstyleprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_ANIMATED_STYLE (gtk_css_animated_style_get_type ())
+#define GTK_CSS_ANIMATED_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyle))
+#define GTK_CSS_ANIMATED_STYLE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyleClass))
+#define GTK_IS_CSS_ANIMATED_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_ANIMATED_STYLE))
+#define GTK_IS_CSS_ANIMATED_STYLE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_ANIMATED_STYLE))
+#define GTK_CSS_ANIMATED_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyleClass))
+
+typedef struct _GtkCssAnimatedStyle GtkCssAnimatedStyle;
+typedef struct _GtkCssAnimatedStyleClass GtkCssAnimatedStyleClass;
+
+struct _GtkCssAnimatedStyle
+{
+ GtkCssStyle parent;
+
+ GPtrArray *values; /* the unanimated (aka intrinsic) values */
+ GPtrArray *sections; /* sections the values are defined in */
+
+ GPtrArray *animated_values; /* NULL or array of animated values/NULL if not animated */
+ gint64 current_time; /* the current time in our world */
+ GSList *animations; /* the running animations, least important one first */
+
+ GtkBitmask *depends_on_parent; /* for intrinsic values */
+ GtkBitmask *equals_parent; /* dito */
+ GtkBitmask *depends_on_color; /* dito */
+ GtkBitmask *depends_on_font_size; /* dito */
+};
+
+struct _GtkCssAnimatedStyleClass
+{
+ GtkCssStyleClass parent_class;
+};
+
+GType gtk_css_animated_style_get_type (void) G_GNUC_CONST;
+
+GtkCssStyle * gtk_css_animated_style_new (void);
+
+void gtk_css_animated_style_compute_value (GtkCssAnimatedStyle *style,
+ GtkStyleProviderPrivate*provider,
+ int scale,
+ GtkCssStyle *parent_style,
+ guint id,
+ GtkCssValue *specified,
+ GtkCssSection *section);
+void gtk_css_animated_style_set_animated_value(GtkCssAnimatedStyle *style,
+ guint id,
+ GtkCssValue *value);
+
+GtkCssValue * gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
+ guint id);
+
+void gtk_css_animated_style_create_animations(GtkCssAnimatedStyle *style,
+ GtkCssAnimatedStyle *parent_style,
+ gint64 timestamp,
+ GtkStyleProviderPrivate*provider,
+ int scale,
+ GtkCssAnimatedStyle *source);
+GtkBitmask * gtk_css_animated_style_advance (GtkCssAnimatedStyle *style,
+ gint64 timestamp);
+void gtk_css_animated_style_cancel_animations(GtkCssAnimatedStyle *style);
+gboolean gtk_css_animated_style_is_static (GtkCssAnimatedStyle *style);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_ANIMATED_STYLE_PRIVATE_H__ */
diff --git a/gtk/gtkcssanimation.c b/gtk/gtkcssanimation.c
index 8ffb537e83..601e4064ca 100644
--- a/gtk/gtkcssanimation.c
+++ b/gtk/gtkcssanimation.c
@@ -104,7 +104,7 @@ gtk_css_animation_get_progress_from_iteration (GtkCssAnimation *animation,
static void
gtk_css_animation_set_values (GtkStyleAnimation *style_animation,
gint64 for_time_us,
- GtkCssStyle *values)
+ GtkCssAnimatedStyle *style)
{
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
double iteration, progress;
@@ -128,8 +128,8 @@ gtk_css_animation_set_values (GtkStyleAnimation *style_animation,
value = _gtk_css_keyframes_get_value (animation->keyframes,
i,
progress,
- gtk_css_style_get_intrinsic_value (values, property_id));
- gtk_css_style_set_animated_value (values, property_id, value);
+ gtk_css_animated_style_get_intrinsic_value (style, property_id));
+ gtk_css_animated_style_set_animated_value (style, property_id, value);
_gtk_css_value_unref (value);
}
}
diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c
index ed586016ee..0e2a952a8b 100644
--- a/gtk/gtkcsslookup.c
+++ b/gtk/gtkcsslookup.c
@@ -106,15 +106,15 @@ void
_gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProviderPrivate *provider,
int scale,
- GtkCssStyle *values,
- GtkCssStyle *parent_values)
+ GtkCssAnimatedStyle *style,
+ GtkCssStyle *parent_style)
{
guint i, n;
g_return_if_fail (lookup != NULL);
g_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
- g_return_if_fail (GTK_IS_CSS_STYLE (values));
- g_return_if_fail (parent_values == NULL || GTK_IS_CSS_STYLE (parent_values));
+ g_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+ g_return_if_fail (parent_style == NULL || GTK_IS_CSS_ANIMATED_STYLE (parent_style));
n = _gtk_css_style_property_get_n_properties ();
@@ -122,13 +122,13 @@ _gtk_css_lookup_resolve (GtkCssLookup *lookup,
{
if (lookup->values[i].value ||
_gtk_bitmask_get (lookup->missing, i))
- gtk_css_style_compute_value (values,
- provider,
- scale,
- parent_values,
- i,
- lookup->values[i].value,
- lookup->values[i].section);
+ gtk_css_animated_style_compute_value (style,
+ provider,
+ scale,
+ parent_style,
+ i,
+ lookup->values[i].value,
+ lookup->values[i].section);
/* else not a relevant property */
}
}
diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h
index 897fe9e39a..2b53e4ace6 100644
--- a/gtk/gtkcsslookupprivate.h
+++ b/gtk/gtkcsslookupprivate.h
@@ -20,7 +20,7 @@
#include <glib-object.h>
#include "gtk/gtkbitmaskprivate.h"
-#include "gtk/gtkcssstyleprivate.h"
+#include "gtk/gtkcssanimatedstyleprivate.h"
#include "gtk/gtkcsssection.h"
@@ -51,8 +51,8 @@ void _gtk_css_lookup_set (GtkCssLookup
void _gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProviderPrivate *provider,
int scale,
- GtkCssStyle *values,
- GtkCssStyle *parent_values);
+ GtkCssAnimatedStyle *style,
+ GtkCssStyle *parent_style);
static inline const GtkBitmask *
_gtk_css_lookup_get_missing (const GtkCssLookup *lookup)
diff --git a/gtk/gtkcssstyle.c b/gtk/gtkcssstyle.c
index 21c89a1dc5..f24557c65f 100644
--- a/gtk/gtkcssstyle.c
+++ b/gtk/gtkcssstyle.c
@@ -37,170 +37,32 @@
#include "gtkstylepropertyprivate.h"
#include "gtkstyleproviderprivate.h"
-G_DEFINE_TYPE (GtkCssStyle, gtk_css_style, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE (GtkCssStyle, gtk_css_style, G_TYPE_OBJECT)
-static void
-gtk_css_style_dispose (GObject *object)
+static GtkCssSection *
+gtk_css_style_real_get_section (GtkCssStyle *style,
+ guint id)
{
- GtkCssStyle *style = GTK_CSS_STYLE (object);
-
- if (style->values)
- {
- g_ptr_array_unref (style->values);
- style->values = NULL;
- }
- if (style->sections)
- {
- g_ptr_array_unref (style->sections);
- style->sections = NULL;
- }
- if (style->animated_values)
- {
- g_ptr_array_unref (style->animated_values);
- style->animated_values = NULL;
- }
-
- g_slist_free_full (style->animations, g_object_unref);
- style->animations = NULL;
-
- G_OBJECT_CLASS (gtk_css_style_parent_class)->dispose (object);
+ return NULL;
}
-static void
-gtk_css_style_finalize (GObject *object)
+static GtkBitmask *
+gtk_css_style_real_compute_dependencies (GtkCssStyle *style,
+ const GtkBitmask *parent_changes)
{
- GtkCssStyle *style = GTK_CSS_STYLE (object);
-
- _gtk_bitmask_free (style->depends_on_parent);
- _gtk_bitmask_free (style->equals_parent);
- _gtk_bitmask_free (style->depends_on_color);
- _gtk_bitmask_free (style->depends_on_font_size);
-
- G_OBJECT_CLASS (gtk_css_style_parent_class)->finalize (object);
+ return _gtk_bitmask_copy (parent_changes);
}
static void
gtk_css_style_class_init (GtkCssStyleClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = gtk_css_style_dispose;
- object_class->finalize = gtk_css_style_finalize;
+ klass->get_section = gtk_css_style_real_get_section;
+ klass->compute_dependencies = gtk_css_style_real_compute_dependencies;
}
static void
gtk_css_style_init (GtkCssStyle *style)
{
- style->depends_on_parent = _gtk_bitmask_new ();
- style->equals_parent = _gtk_bitmask_new ();
- style->depends_on_color = _gtk_bitmask_new ();
- style->depends_on_font_size = _gtk_bitmask_new ();
-}
-
-GtkCssStyle *
-gtk_css_style_new (void)
-{
- return g_object_new (GTK_TYPE_CSS_STYLE, NULL);
-}
-
-static void
-maybe_unref_section (gpointer section)
-{
- if (section)
- gtk_css_section_unref (section);
-}
-
-void
-gtk_css_style_compute_value (GtkCssStyle *style,
- GtkStyleProviderPrivate *provider,
- int scale,
- GtkCssStyle *parent_style,
- guint id,
- GtkCssValue *specified,
- GtkCssSection *section)
-{
- GtkCssDependencies dependencies;
- GtkCssValue *value;
-
- gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
- gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
- gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
-
- /* http://www.w3.org/TR/css3-cascade/#cascade
- * Then, for every element, the value for each property can be found
- * by following this pseudo-algorithm:
- * 1) Identify all declarations that apply to the element
- */
- if (specified == NULL)
- {
- GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (id);
-
- if (_gtk_css_style_property_is_inherit (prop))
- specified = _gtk_css_inherit_value_new ();
- else
- specified = _gtk_css_initial_value_new ();
- }
- else
- _gtk_css_value_ref (specified);
-
- value = _gtk_css_value_compute (specified, id, provider, scale, style, parent_style, &dependencies);
-
- if (style->values == NULL)
- style->values = g_ptr_array_new_full (_gtk_css_style_property_get_n_properties (),
- (GDestroyNotify)_gtk_css_value_unref);
- if (id >= style->values->len)
- g_ptr_array_set_size (style->values, id + 1);
-
- if (g_ptr_array_index (style->values, id))
- _gtk_css_value_unref (g_ptr_array_index (style->values, id));
- g_ptr_array_index (style->values, id) = _gtk_css_value_ref (value);
-
- if (dependencies & (GTK_CSS_DEPENDS_ON_PARENT | GTK_CSS_EQUALS_PARENT))
- style->depends_on_parent = _gtk_bitmask_set (style->depends_on_parent, id, TRUE);
- if (dependencies & (GTK_CSS_EQUALS_PARENT))
- style->equals_parent = _gtk_bitmask_set (style->equals_parent, id, TRUE);
- if (dependencies & (GTK_CSS_DEPENDS_ON_COLOR))
- style->depends_on_color = _gtk_bitmask_set (style->depends_on_color, id, TRUE);
- if (dependencies & (GTK_CSS_DEPENDS_ON_FONT_SIZE))
- style->depends_on_font_size = _gtk_bitmask_set (style->depends_on_font_size, id, TRUE);
-
- if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
- {
- gtk_css_section_unref (g_ptr_array_index (style->sections, id));
- g_ptr_array_index (style->sections, id) = NULL;
- }
-
- if (section)
- {
- if (style->sections == NULL)
- style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
- if (style->sections->len <= id)
- g_ptr_array_set_size (style->sections, id + 1);
-
- g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
- }
-
- _gtk_css_value_unref (value);
- _gtk_css_value_unref (specified);
-}
-
-void
-gtk_css_style_set_animated_value (GtkCssStyle *style,
- guint id,
- GtkCssValue *value)
-{
- gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
- gtk_internal_return_if_fail (value != NULL);
-
- if (style->animated_values == NULL)
- style->animated_values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
- if (id >= style->animated_values->len)
- g_ptr_array_set_size (style->animated_values, id + 1);
-
- if (g_ptr_array_index (style->animated_values, id))
- _gtk_css_value_unref (g_ptr_array_index (style->animated_values, id));
- g_ptr_array_index (style->animated_values, id) = _gtk_css_value_ref (value);
-
}
GtkCssValue *
@@ -209,25 +71,7 @@ gtk_css_style_get_value (GtkCssStyle *style,
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
- if (style->animated_values &&
- id < style->animated_values->len &&
- g_ptr_array_index (style->animated_values, id))
- return g_ptr_array_index (style->animated_values, id);
-
- return gtk_css_style_get_intrinsic_value (style, id);
-}
-
-GtkCssValue *
-gtk_css_style_get_intrinsic_value (GtkCssStyle *style,
- guint id)
-{
- gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
-
- if (style->values == NULL ||
- id >= style->values->len)
- return NULL;
-
- return g_ptr_array_index (style->values, id);
+ return GTK_CSS_STYLE_GET_CLASS (style)->get_value (style, id);
}
GtkCssSection *
@@ -236,11 +80,7 @@ gtk_css_style_get_section (GtkCssStyle *style,
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
- if (style->sections == NULL ||
- id >= style->sections->len)
- return NULL;
-
- return g_ptr_array_index (style->sections, id);
+ return GTK_CSS_STYLE_GET_CLASS (style)->get_section (style, id);
}
GtkBitmask *
@@ -250,369 +90,25 @@ gtk_css_style_get_difference (GtkCssStyle *style,
GtkBitmask *result;
guint i, len;
- len = MIN (style->values->len, other->values->len);
result = _gtk_bitmask_new ();
- if (style->values->len != other->values->len)
- result = _gtk_bitmask_invert_range (result, len, MAX (style->values->len, other->values->len));
-
+ len = _gtk_css_style_property_get_n_properties ();
for (i = 0; i < len; i++)
{
- if (!_gtk_css_value_equal (g_ptr_array_index (style->values, i),
- g_ptr_array_index (other->values, i)))
+ if (!_gtk_css_value_equal (gtk_css_style_get_value (style, i),
+ gtk_css_style_get_value (other, i)))
result = _gtk_bitmask_set (result, i, TRUE);
}
return result;
}
-/* TRANSITIONS */
-
-typedef struct _TransitionInfo TransitionInfo;
-struct _TransitionInfo {
- guint index; /* index into value arrays */
- gboolean pending; /* TRUE if we still need to handle it */
-};
-
-static void
-transition_info_add (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES],
- GtkStyleProperty *property,
- guint index)
-{
- if (property == NULL)
- {
- guint i;
-
- for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
- {
- GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
-
- transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
- }
- }
- else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
- {
- GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
- guint i;
-
- for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
- {
- GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
-
- transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
- }
- }
- else if (GTK_IS_CSS_STYLE_PROPERTY (property))
- {
- guint id;
-
- if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property)))
- return;
-
- id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property));
- g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES);
- infos[id].index = index;
- infos[id].pending = TRUE;
- }
- else
- {
- g_assert_not_reached ();
- }
-}
-
-static void
-transition_infos_set (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES],
- GtkCssValue *transitions)
-{
- guint i;
-
- for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++)
- {
- GtkStyleProperty *property;
- GtkCssValue *prop_value;
-
- prop_value = _gtk_css_array_value_get_nth (transitions, i);
- if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0)
- property = NULL;
- else
- {
- property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value));
- if (property == NULL)
- continue;
- }
-
- transition_info_add (infos, property, i);
- }
-}
-
-static GtkStyleAnimation *
-gtk_css_style_find_transition (GtkCssStyle *style,
- guint property_id)
-{
- GSList *list;
-
- for (list = style->animations; list; list = list->next)
- {
- if (!GTK_IS_CSS_TRANSITION (list->data))
- continue;
-
- if (_gtk_css_transition_get_property (list->data) == property_id)
- return list->data;
- }
-
- return NULL;
-}
-
-static void
-gtk_css_style_create_css_transitions (GtkCssStyle *style,
- gint64 timestamp,
- GtkCssStyle *source)
-{
- TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
- GtkCssValue *durations, *delays, *timing_functions;
- guint i;
-
- transition_infos_set (transitions, gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));
-
- durations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_DURATION);
- delays = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_DELAY);
- timing_functions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);
-
- for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
- {
- GtkStyleAnimation *animation;
- GtkCssValue *start, *end;
- double duration, delay;
-
- if (!transitions[i].pending)
- continue;
-
- duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
- delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
- if (duration + delay == 0.0)
- continue;
-
- start = gtk_css_style_get_intrinsic_value (source, i);
- end = gtk_css_style_get_intrinsic_value (style, i);
- if (_gtk_css_value_equal (start, end))
- {
- animation = gtk_css_style_find_transition (GTK_CSS_STYLE (source), i);
- if (animation)
- style->animations = g_slist_prepend (style->animations, g_object_ref (animation));
- }
- else
- {
- animation = _gtk_css_transition_new (i,
- gtk_css_style_get_value (source, i),
- _gtk_css_array_value_get_nth (timing_functions, i),
- timestamp + delay * G_USEC_PER_SEC,
- timestamp + (delay + duration) * G_USEC_PER_SEC);
- style->animations = g_slist_prepend (style->animations, animation);
- }
- }
-}
-
-static GtkStyleAnimation *
-gtk_css_style_find_animation (GtkCssStyle *style,
- const char *name)
-{
- GSList *list;
-
- for (list = style->animations; list; list = list->next)
- {
- if (!GTK_IS_CSS_ANIMATION (list->data))
- continue;
-
- if (g_str_equal (_gtk_css_animation_get_name (list->data), name))
- return list->data;
- }
-
- return NULL;
-}
-
-static void
-gtk_css_style_create_css_animations (GtkCssStyle *style,
- GtkCssStyle *parent_style,
- gint64 timestamp,
- GtkStyleProviderPrivate *provider,
- int scale,
- GtkCssStyle *source)
-{
- GtkCssValue *durations, *delays, *timing_functions, *animations;
- GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
- guint i;
-
- animations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_NAME);
- durations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DURATION);
- delays = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DELAY);
- timing_functions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
- iteration_counts = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
- directions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
- play_states = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
- fill_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);
-
- for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
- {
- GtkStyleAnimation *animation;
- GtkCssKeyframes *keyframes;
- const char *name;
-
- name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
- if (g_ascii_strcasecmp (name, "none") == 0)
- continue;
-
- animation = gtk_css_style_find_animation (style, name);
- if (animation)
- continue;
-
- if (source)
- animation = gtk_css_style_find_animation (source, name);
-
- if (animation)
- {
- animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
- timestamp,
- _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
- }
- else
- {
- keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
- if (keyframes == NULL)
- continue;
-
- keyframes = _gtk_css_keyframes_compute (keyframes, provider, scale, style, parent_style);
-
- animation = _gtk_css_animation_new (name,
- keyframes,
- timestamp,
- _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
- _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
- _gtk_css_array_value_get_nth (timing_functions, i),
- _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
- _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
- _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
- _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
- _gtk_css_keyframes_unref (keyframes);
- }
- style->animations = g_slist_prepend (style->animations, animation);
- }
-}
-
-/* PUBLIC API */
-
-void
-gtk_css_style_create_animations (GtkCssStyle *style,
- GtkCssStyle *parent_style,
- gint64 timestamp,
- GtkStyleProviderPrivate *provider,
- int scale,
- GtkCssStyle *source)
-{
- if (source != NULL)
- gtk_css_style_create_css_transitions (style, timestamp, source);
- gtk_css_style_create_css_animations (style, parent_style, timestamp, provider, scale, source);
-}
-
-GtkBitmask *
-gtk_css_style_advance (GtkCssStyle *style,
- gint64 timestamp)
-{
- GtkBitmask *changed;
- GPtrArray *old_computed_values;
- GSList *list;
- guint i;
-
- gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
- gtk_internal_return_val_if_fail (timestamp >= style->current_time, NULL);
-
- style->current_time = timestamp;
- old_computed_values = style->animated_values;
- style->animated_values = NULL;
-
- list = style->animations;
- while (list)
- {
- GtkStyleAnimation *animation = list->data;
-
- list = list->next;
-
- _gtk_style_animation_set_values (animation,
- timestamp,
- GTK_CSS_STYLE (style));
-
- if (_gtk_style_animation_is_finished (animation, timestamp))
- {
- style->animations = g_slist_remove (style->animations, animation);
- g_object_unref (animation);
- }
- }
-
- /* figure out changes */
- changed = _gtk_bitmask_new ();
-
- for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
- {
- GtkCssValue *old_animated, *new_animated;
-
- old_animated = old_computed_values && i < old_computed_values->len ? g_ptr_array_index (old_computed_values, i) : NULL;
- new_animated = style->animated_values && i < style->animated_values->len ? g_ptr_array_index (style->animated_values, i) : NULL;
-
- if (!_gtk_css_value_equal0 (old_animated, new_animated))
- changed = _gtk_bitmask_set (changed, i, TRUE);
- }
-
- if (old_computed_values)
- g_ptr_array_unref (old_computed_values);
-
- return changed;
-}
-
-gboolean
-gtk_css_style_is_static (GtkCssStyle *style)
-{
- GSList *list;
-
- gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), TRUE);
-
- for (list = style->animations; list; list = list->next)
- {
- if (!_gtk_style_animation_is_static (list->data, style->current_time))
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
-gtk_css_style_cancel_animations (GtkCssStyle *style)
-{
- gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
-
- if (style->animated_values)
- {
- g_ptr_array_unref (style->animated_values);
- style->animated_values = NULL;
- }
-
- g_slist_free_full (style->animations, g_object_unref);
- style->animations = NULL;
-}
-
GtkBitmask *
gtk_css_style_compute_dependencies (GtkCssStyle *style,
const GtkBitmask *parent_changes)
{
- GtkBitmask *changes;
-
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), _gtk_bitmask_new ());
- changes = _gtk_bitmask_copy (parent_changes);
- changes = _gtk_bitmask_intersect (changes, style->depends_on_parent);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
- changes = _gtk_bitmask_union (changes, style->depends_on_color);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
- changes = _gtk_bitmask_union (changes, style->depends_on_font_size);
-
- return changes;
+ return GTK_CSS_STYLE_GET_CLASS (style)->compute_dependencies (style, parent_changes);
}
void
diff --git a/gtk/gtkcssstyleprivate.h b/gtk/gtkcssstyleprivate.h
index f566426561..d61b4c3cf9 100644
--- a/gtk/gtkcssstyleprivate.h
+++ b/gtk/gtkcssstyleprivate.h
@@ -41,62 +41,39 @@ typedef struct _GtkCssStyleClass GtkCssStyleClass;
struct _GtkCssStyle
{
GObject parent;
-
- GPtrArray *values; /* the unanimated (aka intrinsic) values */
- GPtrArray *sections; /* sections the values are defined in */
-
- GPtrArray *animated_values; /* NULL or array of animated values/NULL if not animated */
- gint64 current_time; /* the current time in our world */
- GSList *animations; /* the running animations, least important one first */
-
- GtkBitmask *depends_on_parent; /* for intrinsic values */
- GtkBitmask *equals_parent; /* dito */
- GtkBitmask *depends_on_color; /* dito */
- GtkBitmask *depends_on_font_size; /* dito */
};
struct _GtkCssStyleClass
{
GObjectClass parent_class;
+
+ /* Get the value for the given property id. This needs to be FAST. */
+ GtkCssValue * (* get_value) (GtkCssStyle *style,
+ guint id);
+ /* Get the section the value at the given id was declared at or NULL if unavailable.
+ * Optional: default impl will just return NULL */
+ GtkCssSection * (* get_section) (GtkCssStyle *style,
+ guint id);
+ /* Compute the bitmask of potentially changed properties if the parent has changed
+ * the passed in ones.
+ * This is for example needed when changes in the "color" property will affect
+ * all properties using "currentColor" as a color.
+ * Optional: The default impl just returns the parent changes unchanged */
+ GtkBitmask * (* compute_dependencies) (GtkCssStyle *style,
+ const GtkBitmask *parent_changes);
};
GType gtk_css_style_get_type (void) G_GNUC_CONST;
-GtkCssStyle * gtk_css_style_new (void);
-
-void gtk_css_style_compute_value (GtkCssStyle *style,
- GtkStyleProviderPrivate*provider,
- int scale,
- GtkCssStyle *parent_style,
- guint id,
- GtkCssValue *specified,
- GtkCssSection *section);
-void gtk_css_style_set_animated_value (GtkCssStyle *style,
- guint id,
- GtkCssValue *value);
-
GtkCssValue * gtk_css_style_get_value (GtkCssStyle *style,
guint id);
GtkCssSection * gtk_css_style_get_section (GtkCssStyle *style,
guint id);
-GtkCssValue * gtk_css_style_get_intrinsic_value (GtkCssStyle *style,
- guint id);
GtkBitmask * gtk_css_style_get_difference (GtkCssStyle *style,
GtkCssStyle *other);
GtkBitmask * gtk_css_style_compute_dependencies (GtkCssStyle *style,
const GtkBitmask *parent_changes);
-void gtk_css_style_create_animations (GtkCssStyle *style,
- GtkCssStyle *parent_style,
- gint64 timestamp,
- GtkStyleProviderPrivate*provider,
- int scale,
- GtkCssStyle *source);
-GtkBitmask * gtk_css_style_advance (GtkCssStyle *style,
- gint64 timestamp);
-void gtk_css_style_cancel_animations (GtkCssStyle *style);
-gboolean gtk_css_style_is_static (GtkCssStyle *style);
-
char * gtk_css_style_to_string (GtkCssStyle *style);
void gtk_css_style_print (GtkCssStyle *style,
GString *string);
diff --git a/gtk/gtkcsstransition.c b/gtk/gtkcsstransition.c
index 0d0f58119f..747bac1dc7 100644
--- a/gtk/gtkcsstransition.c
+++ b/gtk/gtkcsstransition.c
@@ -26,15 +26,15 @@
G_DEFINE_TYPE (GtkCssTransition, _gtk_css_transition, GTK_TYPE_STYLE_ANIMATION)
static void
-gtk_css_transition_set_values (GtkStyleAnimation *animation,
- gint64 for_time_us,
- GtkCssStyle *style)
+gtk_css_transition_set_values (GtkStyleAnimation *animation,
+ gint64 for_time_us,
+ GtkCssAnimatedStyle *style)
{
GtkCssTransition *transition = GTK_CSS_TRANSITION (animation);
GtkCssValue *value, *end;
double progress;
- end = gtk_css_style_get_intrinsic_value (style, transition->property);
+ end = gtk_css_animated_style_get_intrinsic_value (style, transition->property);
if (transition->start_time >= for_time_us)
value = _gtk_css_value_ref (transition->start);
@@ -55,7 +55,7 @@ gtk_css_transition_set_values (GtkStyleAnimation *animation,
if (value)
{
- gtk_css_style_set_animated_value (style, transition->property, value);
+ gtk_css_animated_style_set_animated_value (style, transition->property, value);
_gtk_css_value_unref (value);
}
}
diff --git a/gtk/gtkstyleanimation.c b/gtk/gtkstyleanimation.c
index 7bca5b7022..3c1a8876c7 100644
--- a/gtk/gtkstyleanimation.c
+++ b/gtk/gtkstyleanimation.c
@@ -26,7 +26,7 @@ G_DEFINE_ABSTRACT_TYPE (GtkStyleAnimation, _gtk_style_animation, G_TYPE_OBJECT)
static void
gtk_style_animation_real_set_values (GtkStyleAnimation *animation,
gint64 for_time_us,
- GtkCssStyle *values)
+ GtkCssAnimatedStyle *style)
{
}
@@ -60,16 +60,16 @@ _gtk_style_animation_init (GtkStyleAnimation *animation)
void
_gtk_style_animation_set_values (GtkStyleAnimation *animation,
gint64 for_time_us,
- GtkCssStyle *values)
+ GtkCssAnimatedStyle *style)
{
GtkStyleAnimationClass *klass;
g_return_if_fail (GTK_IS_STYLE_ANIMATION (animation));
- g_return_if_fail (GTK_IS_CSS_STYLE (values));
+ g_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
- return klass->set_values (animation, for_time_us, values);
+ klass->set_values (animation, for_time_us, style);
}
gboolean
diff --git a/gtk/gtkstyleanimationprivate.h b/gtk/gtkstyleanimationprivate.h
index fbeb9d7817..6981004376 100644
--- a/gtk/gtkstyleanimationprivate.h
+++ b/gtk/gtkstyleanimationprivate.h
@@ -20,8 +20,7 @@
#ifndef __GTK_STYLE_ANIMATION_PRIVATE_H__
#define __GTK_STYLE_ANIMATION_PRIVATE_H__
-#include <glib-object.h>
-#include "gtkcssstyleprivate.h"
+#include "gtkcssanimatedstyleprivate.h"
G_BEGIN_DECLS
@@ -50,14 +49,14 @@ struct _GtkStyleAnimationClass
gint64 at_time_us);
void (* set_values) (GtkStyleAnimation *animation,
gint64 for_time_us,
- GtkCssStyle *values);
+ GtkCssAnimatedStyle *style);
};
GType _gtk_style_animation_get_type (void) G_GNUC_CONST;
void _gtk_style_animation_set_values (GtkStyleAnimation *animation,
gint64 for_time_us,
- GtkCssStyle *values);
+ GtkCssAnimatedStyle *style);
gboolean _gtk_style_animation_is_finished (GtkStyleAnimation *animation,
gint64 at_time_us);
gboolean _gtk_style_animation_is_static (GtkStyleAnimation *animation,
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index cdd66f0cbe..479bf14a3a 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -503,7 +503,7 @@ gtk_style_context_should_animate (GtkStyleContext *context)
return FALSE;
values = style_values_lookup (context);
- if (gtk_css_style_is_static (values))
+ if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
return FALSE;
g_object_get (gtk_widget_get_settings (context->priv->widget),
@@ -704,7 +704,7 @@ build_properties (GtkStyleContext *context,
_gtk_css_lookup_resolve (lookup,
GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
priv->scale,
- values,
+ GTK_CSS_ANIMATED_STYLE (values),
priv->parent ? style_values_lookup (priv->parent) : NULL);
_gtk_css_lookup_free (lookup);
@@ -734,7 +734,7 @@ style_values_lookup (GtkStyleContext *context)
return values;
}
- values = gtk_css_style_new ();
+ values = gtk_css_animated_style_new ();
style_info_set_values (info, values);
if (gtk_style_context_is_saved (context))
@@ -772,7 +772,7 @@ style_values_lookup_for_state (GtkStyleContext *context,
decl = gtk_css_node_declaration_ref (context->priv->info->decl);
gtk_css_node_declaration_set_state (&decl, state);
- values = gtk_css_style_new ();
+ values = gtk_css_animated_style_new ();
build_properties (context, values, decl, NULL, NULL);
gtk_css_node_declaration_unref (decl);
@@ -2696,9 +2696,9 @@ gtk_style_context_update_animations (GtkStyleContext *context,
values = style_values_lookup (context);
- differences = gtk_css_style_advance (values, timestamp);
+ differences = gtk_css_animated_style_advance (GTK_CSS_ANIMATED_STYLE (values), timestamp);
- if (gtk_css_style_is_static (values))
+ if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
_gtk_style_context_update_animating (context);
return differences;
@@ -2805,13 +2805,15 @@ _gtk_style_context_validate (GtkStyleContext *context,
values = style_values_lookup (context);
if (values != current)
- gtk_css_style_create_animations (values,
- priv->parent ? style_values_lookup (priv->parent) : NULL,
- timestamp,
- GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
- priv->scale,
- gtk_style_context_should_create_transitions (context) ? current : NULL);
- if (gtk_css_style_is_static (values))
+ gtk_css_animated_style_create_animations (GTK_CSS_ANIMATED_STYLE (values),
+ priv->parent ? GTK_CSS_ANIMATED_STYLE (style_values_lookup (priv->parent)) : NULL,
+ timestamp,
+ GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ priv->scale,
+ gtk_style_context_should_create_transitions (context)
+ ? GTK_CSS_ANIMATED_STYLE (current)
+ : NULL);
+ if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
change &= ~GTK_CSS_CHANGE_ANIMATE;
else
change |= GTK_CSS_CHANGE_ANIMATE;