cssanimation: port to progress tracker

This commit is contained in:
Matt Watson 2016-03-24 23:43:15 -07:00
parent 50e057e025
commit 2800b00e1d
3 changed files with 51 additions and 75 deletions

View File

@ -369,7 +369,6 @@ gtk_css_animated_style_create_css_animations (GSList *animation
if (animation) if (animation)
{ {
animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (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))); _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
} }
else else

View File

@ -22,41 +22,25 @@
#include "gtkcssanimationprivate.h" #include "gtkcssanimationprivate.h"
#include "gtkcsseasevalueprivate.h" #include "gtkcsseasevalueprivate.h"
#include "gtkprogresstrackerprivate.h"
#include <math.h> #include <math.h>
G_DEFINE_TYPE (GtkCssAnimation, _gtk_css_animation, GTK_TYPE_STYLE_ANIMATION) G_DEFINE_TYPE (GtkCssAnimation, _gtk_css_animation, GTK_TYPE_STYLE_ANIMATION)
/* NB: Return value can be negative (if animation hasn't started yet) */
static gint64
gtk_css_animation_get_elapsed (GtkCssAnimation *animation,
gint64 for_time_us)
{
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
return animation->timestamp;
else
return for_time_us - animation->timestamp;
}
/* NB: Return value can be negative and +-Inf */
static double
gtk_css_animation_get_iteration (GtkCssAnimation *animation,
gint64 for_time_us)
{
return (double) gtk_css_animation_get_elapsed (animation, for_time_us) / animation->duration;
}
static gboolean static gboolean
gtk_css_animation_is_executing_at_iteration (GtkCssAnimation *animation, gtk_css_animation_is_executing (GtkCssAnimation *animation)
double iteration)
{ {
GtkProgressState state = gtk_progress_tracker_get_state (&animation->tracker);
switch (animation->fill_mode) switch (animation->fill_mode)
{ {
case GTK_CSS_FILL_NONE: case GTK_CSS_FILL_NONE:
return iteration >= 0 && iteration <= animation->iteration_count; return state == GTK_PROGRESS_STATE_DURING;
case GTK_CSS_FILL_FORWARDS: case GTK_CSS_FILL_FORWARDS:
return iteration >= 0; return state != GTK_PROGRESS_STATE_BEFORE;
case GTK_CSS_FILL_BACKWARDS: case GTK_CSS_FILL_BACKWARDS:
return iteration <= animation->iteration_count; return state != GTK_PROGRESS_STATE_AFTER;
case GTK_CSS_FILL_BOTH: case GTK_CSS_FILL_BOTH:
return TRUE; return TRUE;
default: default:
@ -65,38 +49,31 @@ gtk_css_animation_is_executing_at_iteration (GtkCssAnimation *animation,
} }
static double static double
gtk_css_animation_get_progress_from_iteration (GtkCssAnimation *animation, gtk_css_animation_get_progress (GtkCssAnimation *animation)
double iteration)
{ {
gboolean reverse; gboolean reverse, odd_iteration;
double completed; gint cycle = gtk_progress_tracker_get_iteration_cycle (&animation->tracker);
odd_iteration = cycle % 2 > 0;
iteration = CLAMP (iteration, 0.0, animation->iteration_count);
completed = floor (iteration);
switch (animation->direction) switch (animation->direction)
{ {
case GTK_CSS_DIRECTION_NORMAL: case GTK_CSS_DIRECTION_NORMAL:
reverse = completed == iteration && iteration > 0; reverse = FALSE;
break; break;
case GTK_CSS_DIRECTION_REVERSE: case GTK_CSS_DIRECTION_REVERSE:
reverse = !(completed == iteration && iteration > 0); reverse = TRUE;
break; break;
case GTK_CSS_DIRECTION_ALTERNATE: case GTK_CSS_DIRECTION_ALTERNATE:
reverse = fmod (iteration, 2) >= 1.0; reverse = odd_iteration;
break; break;
case GTK_CSS_DIRECTION_ALTERNATE_REVERSE: case GTK_CSS_DIRECTION_ALTERNATE_REVERSE:
reverse = !(fmod (iteration, 2) >= 1.0); reverse = !odd_iteration;
break; break;
default: default:
g_return_val_if_reached (0.0); g_return_val_if_reached (0.0);
} }
iteration -= completed; return gtk_progress_tracker_get_progress (&animation->tracker, reverse);
if (reverse)
iteration = 1.0 - iteration;
return iteration;
} }
static void static void
@ -105,17 +82,20 @@ gtk_css_animation_set_values (GtkStyleAnimation *style_animation,
GtkCssAnimatedStyle *style) GtkCssAnimatedStyle *style)
{ {
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation); GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
double iteration, progress; double progress;
guint i; guint i;
iteration = gtk_css_animation_get_iteration (animation, for_time_us); if (animation->play_state != GTK_CSS_PLAY_STATE_PAUSED)
gtk_progress_tracker_advance_frame (&animation->tracker, for_time_us);
else
gtk_progress_tracker_skip_frame (&animation->tracker, for_time_us);
if (!gtk_css_animation_is_executing_at_iteration (animation, iteration)) if (!gtk_css_animation_is_executing (animation))
return; return;
progress = gtk_css_animation_get_progress_from_iteration (animation, iteration); progress = gtk_css_animation_get_progress (animation);
progress = _gtk_css_ease_value_transform (animation->ease, progress); progress = _gtk_css_ease_value_transform (animation->ease, progress);
for (i = 0; i < _gtk_css_keyframes_get_n_properties (animation->keyframes); i++) for (i = 0; i < _gtk_css_keyframes_get_n_properties (animation->keyframes); i++)
{ {
GtkCssValue *value; GtkCssValue *value;
@ -144,14 +124,11 @@ gtk_css_animation_is_static (GtkStyleAnimation *style_animation,
gint64 at_time_us) gint64 at_time_us)
{ {
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation); GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
double iteration;
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED) if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
return TRUE; return TRUE;
iteration = gtk_css_animation_get_iteration (animation, at_time_us); return gtk_progress_tracker_get_state (&animation->tracker) == GTK_PROGRESS_STATE_AFTER;
return iteration >= animation->iteration_count;
} }
static void static void
@ -207,17 +184,16 @@ _gtk_css_animation_new (const char *name,
animation->name = g_strdup (name); animation->name = g_strdup (name);
animation->keyframes = _gtk_css_keyframes_ref (keyframes); animation->keyframes = _gtk_css_keyframes_ref (keyframes);
if (play_state == GTK_CSS_PLAY_STATE_PAUSED)
animation->timestamp = - delay_us;
else
animation->timestamp = timestamp + delay_us;
animation->duration = duration_us;
animation->ease = _gtk_css_value_ref (ease); animation->ease = _gtk_css_value_ref (ease);
animation->direction = direction; animation->direction = direction;
animation->play_state = play_state; animation->play_state = play_state;
animation->fill_mode = fill_mode; animation->fill_mode = fill_mode;
animation->iteration_count = iteration_count;
gtk_progress_tracker_start (&animation->tracker, duration_us, delay_us, iteration_count);
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
gtk_progress_tracker_skip_frame (&animation->tracker, timestamp);
else
gtk_progress_tracker_advance_frame (&animation->tracker, timestamp);
return GTK_STYLE_ANIMATION (animation); return GTK_STYLE_ANIMATION (animation);
} }
@ -231,24 +207,27 @@ _gtk_css_animation_get_name (GtkCssAnimation *animation)
} }
GtkStyleAnimation * GtkStyleAnimation *
_gtk_css_animation_copy (GtkCssAnimation *animation, _gtk_css_animation_copy (GtkCssAnimation *source,
gint64 at_time_us,
GtkCssPlayState play_state) GtkCssPlayState play_state)
{ {
g_return_val_if_fail (GTK_IS_CSS_ANIMATION (animation), NULL); GtkCssAnimation *animation;
if (animation->play_state == play_state) g_return_val_if_fail (GTK_IS_CSS_ANIMATION (source), NULL);
return g_object_ref (animation);
return _gtk_css_animation_new (animation->name, if (source->play_state == play_state)
animation->keyframes, return g_object_ref (source);
at_time_us,
- gtk_css_animation_get_elapsed (animation, at_time_us), animation = g_object_new (GTK_TYPE_CSS_ANIMATION, NULL);
animation->duration,
animation->ease, animation->name = g_strdup (source->name);
animation->direction, animation->keyframes = _gtk_css_keyframes_ref (source->keyframes);
play_state, animation->ease = _gtk_css_value_ref (source->ease);
animation->fill_mode, animation->direction = source->direction;
animation->iteration_count); animation->play_state = play_state;
animation->fill_mode = source->fill_mode;
memcpy (&animation->tracker, &source->tracker, sizeof (source->tracker));
return GTK_STYLE_ANIMATION (animation);
} }

View File

@ -23,6 +23,7 @@
#include "gtkstyleanimationprivate.h" #include "gtkstyleanimationprivate.h"
#include "gtkcsskeyframesprivate.h" #include "gtkcsskeyframesprivate.h"
#include "gtkprogresstrackerprivate.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -43,12 +44,10 @@ struct _GtkCssAnimation
char *name; char *name;
GtkCssKeyframes *keyframes; GtkCssKeyframes *keyframes;
GtkCssValue *ease; GtkCssValue *ease;
gint64 timestamp; /* elapsed time when paused, start time when playing (can be negative) */
gint64 duration; /* duration of 1 cycle */
double iteration_count;
GtkCssDirection direction; GtkCssDirection direction;
GtkCssPlayState play_state; GtkCssPlayState play_state;
GtkCssFillMode fill_mode; GtkCssFillMode fill_mode;
GtkProgressTracker tracker;
}; };
struct _GtkCssAnimationClass struct _GtkCssAnimationClass
@ -70,7 +69,6 @@ GtkStyleAnimation * _gtk_css_animation_new (const char *
double iteration_count); double iteration_count);
GtkStyleAnimation * _gtk_css_animation_copy (GtkCssAnimation *animation, GtkStyleAnimation * _gtk_css_animation_copy (GtkCssAnimation *animation,
gint64 at_time_us,
GtkCssPlayState play_state); GtkCssPlayState play_state);
const char * _gtk_css_animation_get_name (GtkCssAnimation *animation); const char * _gtk_css_animation_get_name (GtkCssAnimation *animation);