diff options
author | Benjamin Otte <otte@redhat.com> | 2012-09-13 18:11:29 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2012-09-17 20:39:12 +0200 |
commit | a7ec3ba53fb9978cf6bae91816f80ad5f5cf88de (patch) | |
tree | 70789c8646e1b966d6d33781c06665daa67c3d6b /gtk/gtkcsscomputedvalues.c | |
parent | 7248c190373ae717b74d24d054a047c8d939efa4 (diff) | |
download | gtk+-a7ec3ba53fb9978cf6bae91816f80ad5f5cf88de.tar.gz |
csscomputedvalues: Get rid of animated values
Merge the animated values code into the computed values code. This
should get rid of various bugs related to animated->computed updating.
Diffstat (limited to 'gtk/gtkcsscomputedvalues.c')
-rw-r--r-- | gtk/gtkcsscomputedvalues.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/gtk/gtkcsscomputedvalues.c b/gtk/gtkcsscomputedvalues.c index ea44341ad9..1450068565 100644 --- a/gtk/gtkcsscomputedvalues.c +++ b/gtk/gtkcsscomputedvalues.c @@ -21,9 +21,20 @@ #include "gtkcsscomputedvaluesprivate.h" +#include "gtkcssanimationprivate.h" +#include "gtkcssarrayvalueprivate.h" +#include "gtkcssenumvalueprivate.h" #include "gtkcssinheritvalueprivate.h" #include "gtkcssinitialvalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcssshorthandpropertyprivate.h" +#include "gtkcssstringvalueprivate.h" #include "gtkcssstylepropertyprivate.h" +#include "gtkcsstransitionprivate.h" +#include "gtkstyleanimationprivate.h" +#include "gtkstylepropertiesprivate.h" +#include "gtkstylepropertyprivate.h" +#include "gtkstyleproviderprivate.h" G_DEFINE_TYPE (GtkCssComputedValues, _gtk_css_computed_values, G_TYPE_OBJECT) @@ -48,6 +59,9 @@ gtk_css_computed_values_dispose (GObject *object) values->animated_values = NULL; } + g_slist_free_full (values->animations, g_object_unref); + values->animations = NULL; + G_OBJECT_CLASS (_gtk_css_computed_values_parent_class)->dispose (object); } @@ -252,3 +266,295 @@ _gtk_css_computed_values_get_difference (GtkCssComputedValues *values, 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_computed_values_find_transition (GtkCssComputedValues *values, + guint property_id) +{ + GSList *list; + + for (list = values->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_computed_values_start_transitions (GtkCssComputedValues *values, + gint64 timestamp, + GtkCssComputedValues *source) +{ + TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } }; + GtkCssValue *durations, *delays, *timing_functions; + guint i; + + transition_infos_set (transitions, _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_PROPERTY)); + + durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DURATION); + delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DELAY); + timing_functions = _gtk_css_computed_values_get_value (values, 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_computed_values_get_intrinsic_value (source, i); + end = _gtk_css_computed_values_get_intrinsic_value (values, i); + if (_gtk_css_value_equal (start, end)) + { + animation = gtk_css_computed_values_find_transition (GTK_CSS_COMPUTED_VALUES (source), i); + if (animation) + values->animations = g_slist_prepend (values->animations, g_object_ref (animation)); + } + else + { + animation = _gtk_css_transition_new (i, + start, + end, + _gtk_css_array_value_get_nth (timing_functions, i), + timestamp + delay * G_USEC_PER_SEC, + timestamp + (delay + duration) * G_USEC_PER_SEC); + values->animations = g_slist_prepend (values->animations, animation); + } + } +} + +static GtkStyleAnimation * +gtk_css_computed_values_find_animation (GtkCssComputedValues *values, + const char *name) +{ + GSList *list; + + for (list = values->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_computed_values_start_css_animations (GtkCssComputedValues *values, + gint64 timestamp, + GtkStyleContext *context) +{ + GtkStyleProviderPrivate *provider; + GtkCssValue *durations, *delays, *timing_functions, *animations; + GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes; + guint i; + + provider = _gtk_style_context_get_style_provider (context); + animations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_NAME); + durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DURATION); + delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DELAY); + timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION); + iteration_counts = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT); + directions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DIRECTION); + play_states = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE); + fill_modes = _gtk_css_computed_values_get_value (values, 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_computed_values_find_animation (values, name); + if (animation) + continue; + + keyframes = _gtk_style_provider_private_get_keyframes (provider, name); + if (keyframes == NULL) + continue; + + keyframes = _gtk_css_keyframes_compute (keyframes, context); + + 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)); + values->animations = g_slist_prepend (values->animations, animation); + } +} + +/* PUBLIC API */ + +void +_gtk_css_computed_values_start_animations (GtkCssComputedValues *values, + gint64 timestamp, + GtkCssComputedValues *source, + GtkStyleContext *context) +{ + GtkBitmask *ignore; + + gtk_css_computed_values_start_transitions (values, timestamp, source); + gtk_css_computed_values_start_css_animations (values, timestamp, context); + + ignore = _gtk_css_computed_values_advance (values, timestamp); + _gtk_bitmask_free (ignore); +} + +GtkBitmask * +_gtk_css_computed_values_advance (GtkCssComputedValues *values, + gint64 timestamp) +{ + GtkBitmask *changed; + GPtrArray *old_computed_values; + GSList *list; + + g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values), NULL); + g_return_val_if_fail (timestamp >= values->current_time, NULL); + + changed = _gtk_bitmask_new (); + + values->current_time = timestamp; + old_computed_values = values->animated_values; + values->animated_values = NULL; + + list = values->animations; + while (list) + { + GtkStyleAnimation *animation = list->data; + + list = list->next; + + changed = _gtk_style_animation_set_values (animation, + changed, + timestamp, + GTK_CSS_COMPUTED_VALUES (values)); + + if (_gtk_style_animation_is_finished (animation, timestamp)) + { + values->animations = g_slist_remove (values->animations, animation); + g_object_unref (animation); + } + } + + if (old_computed_values) + g_ptr_array_unref (old_computed_values); + + return changed; +} + +gboolean +_gtk_css_computed_values_is_static (GtkCssComputedValues *values) +{ + GSList *list; + + g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values), TRUE); + + for (list = values->animations; list; list = list->next) + { + if (!_gtk_style_animation_is_static (list->data, values->current_time)) + return FALSE; + } + + return TRUE; +} |