Commit 9e12979f authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Start untying SVGSMILElement::Progress

To be able to separate the resolution of intervals from the update of
the "position" information (percent, repeat) we need to keep the "full"
previous interval. Extend the existing |previous_interval_begin_| to a
full interval, add a new GetActiveInterval(...) helper and use that
in CalculateAnimation{Repeat,Percent}. Then move the calls to the latter
two functions in Progress() after the interval check/resolution.

Bug: 998526
Change-Id: Ia7154e6612252d21b04ab6302c8ef75bc7664b45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1790449Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#694909}
parent b4f3df4e
...@@ -195,8 +195,8 @@ SVGSMILElement::SVGSMILElement(const QualifiedName& tag_name, Document& doc) ...@@ -195,8 +195,8 @@ SVGSMILElement::SVGSMILElement(const QualifiedName& tag_name, Document& doc)
has_end_event_conditions_(false), has_end_event_conditions_(false),
is_waiting_for_first_interval_(true), is_waiting_for_first_interval_(true),
is_scheduled_(false), is_scheduled_(false),
interval_(SMILInterval(SMILTime::Unresolved(), SMILTime::Unresolved())), interval_{SMILTime::Unresolved(), SMILTime::Unresolved()},
previous_interval_begin_(SMILTime::Unresolved()), previous_interval_{SMILTime::Unresolved(), SMILTime::Unresolved()},
active_state_(kInactive), active_state_(kInactive),
restart_(kRestartAlways), restart_(kRestartAlways),
fill_(kFillRemove), fill_(kFillRemove),
...@@ -275,9 +275,8 @@ void SVGSMILElement::Reset() { ...@@ -275,9 +275,8 @@ void SVGSMILElement::Reset() {
active_state_ = kInactive; active_state_ = kInactive;
is_waiting_for_first_interval_ = true; is_waiting_for_first_interval_ = true;
interval_.begin = SMILTime::Unresolved(); interval_ = {SMILTime::Unresolved(), SMILTime::Unresolved()};
interval_.end = SMILTime::Unresolved(); previous_interval_ = {SMILTime::Unresolved(), SMILTime::Unresolved()};
previous_interval_begin_ = SMILTime::Unresolved();
last_percent_ = 0; last_percent_ = 0;
last_repeat_ = 0; last_repeat_ = 0;
next_progress_time_ = 0; next_progress_time_ = 0;
...@@ -973,16 +972,28 @@ base::Optional<SMILInterval> SVGSMILElement::CheckForNewRestartInterval( ...@@ -973,16 +972,28 @@ base::Optional<SMILInterval> SVGSMILElement::CheckForNewRestartInterval(
return modified; return modified;
} }
const SMILInterval& SVGSMILElement::GetActiveInterval(double elapsed) const {
// If there's no current interval, return the previous interval.
if (!interval_.begin.IsFinite())
return previous_interval_;
// If there's a previous interval and the current interval hasn't begun yet,
// return the previous interval.
if (previous_interval_.begin.IsFinite() && elapsed < interval_.begin)
return previous_interval_;
return interval_;
}
unsigned SVGSMILElement::CalculateAnimationRepeat(double elapsed) const { unsigned SVGSMILElement::CalculateAnimationRepeat(double elapsed) const {
const SMILTime simple_duration = SimpleDuration(); const SMILTime simple_duration = SimpleDuration();
if (simple_duration.IsIndefinite() || !simple_duration) if (simple_duration.IsIndefinite() || !simple_duration)
return 0; return 0;
DCHECK(simple_duration.IsFinite()); DCHECK(simple_duration.IsFinite());
DCHECK(interval_.begin.IsFinite()); const SMILInterval& active_interval = GetActiveInterval(elapsed);
DCHECK(active_interval.begin.IsFinite());
double active_time = std::max(elapsed - interval_.begin.Value(), 0.0); double active_time = std::max(elapsed - active_interval.begin.Value(), 0.0);
SMILTime repeating_duration = RepeatingDuration(); SMILTime repeating_duration = RepeatingDuration();
if (elapsed >= interval_.end || active_time > repeating_duration) { if (elapsed >= active_interval.end || active_time > repeating_duration) {
if (!repeating_duration.IsFinite()) if (!repeating_duration.IsFinite())
return 0; return 0;
unsigned repeat = static_cast<unsigned>(repeating_duration.Value() / unsigned repeat = static_cast<unsigned>(repeating_duration.Value() /
...@@ -1005,20 +1016,23 @@ float SVGSMILElement::CalculateAnimationPercent(double elapsed) const { ...@@ -1005,20 +1016,23 @@ float SVGSMILElement::CalculateAnimationPercent(double elapsed) const {
return 1.f; return 1.f;
} }
DCHECK(simple_duration.IsFinite()); DCHECK(simple_duration.IsFinite());
DCHECK(interval_.begin.IsFinite()); const SMILInterval& active_interval = GetActiveInterval(elapsed);
DCHECK(active_interval.begin.IsFinite());
SMILTime repeating_duration = RepeatingDuration(); SMILTime repeating_duration = RepeatingDuration();
double active_time = elapsed - interval_.begin.Value(); double active_time = elapsed - active_interval.begin.Value();
if (elapsed >= interval_.end || active_time > repeating_duration) { if (elapsed >= active_interval.end || active_time > repeating_duration) {
// Use the interval to compute the interval position if we've passed the // Use the interval to compute the interval position if we've passed the
// interval end, otherwise use the "repeating duration". This prevents a // interval end, otherwise use the "repeating duration". This prevents a
// stale interval (with for instance an 'indefinite' end) from yielding an // stale interval (with for instance an 'indefinite' end) from yielding an
// invalid interval position. // invalid interval position.
double last_active_duration; double last_active_duration;
if (elapsed >= interval_.end) if (elapsed >= active_interval.end) {
last_active_duration = interval_.end.Value() - interval_.begin.Value(); last_active_duration =
else active_interval.end.Value() - active_interval.begin.Value();
} else {
last_active_duration = repeating_duration.Value(); last_active_duration = repeating_duration.Value();
}
double percent = last_active_duration / simple_duration.Value(); double percent = last_active_duration / simple_duration.Value();
percent = percent - floor(percent); percent = percent - floor(percent);
float epsilon = std::numeric_limits<float>::epsilon(); float epsilon = std::numeric_limits<float>::epsilon();
...@@ -1126,9 +1140,6 @@ void SVGSMILElement::UpdateNextProgressTime(double elapsed) { ...@@ -1126,9 +1140,6 @@ void SVGSMILElement::UpdateNextProgressTime(double elapsed) {
} }
void SVGSMILElement::Progress(double elapsed) { void SVGSMILElement::Progress(double elapsed) {
float percent = CalculateAnimationPercent(elapsed);
unsigned repeat = CalculateAnimationRepeat(elapsed);
base::Optional<SMILInterval> new_interval = base::Optional<SMILInterval> new_interval =
CheckForNewRestartInterval(elapsed); CheckForNewRestartInterval(elapsed);
...@@ -1136,7 +1147,7 @@ void SVGSMILElement::Progress(double elapsed) { ...@@ -1136,7 +1147,7 @@ void SVGSMILElement::Progress(double elapsed) {
bool interval_restart = (new_interval && *new_interval != interval_); bool interval_restart = (new_interval && *new_interval != interval_);
if (new_interval) { if (new_interval) {
previous_interval_begin_ = interval_.begin; previous_interval_ = interval_;
interval_ = *new_interval; interval_ = *new_interval;
interval_has_changed_ = true; interval_has_changed_ = true;
} }
...@@ -1150,13 +1161,14 @@ void SVGSMILElement::Progress(double elapsed) { ...@@ -1150,13 +1161,14 @@ void SVGSMILElement::Progress(double elapsed) {
StartedActiveInterval(); StartedActiveInterval();
} }
unsigned repeat = CalculateAnimationRepeat(elapsed);
if (repeat && repeat != last_repeat_) { if (repeat && repeat != last_repeat_) {
last_repeat_ = repeat; last_repeat_ = repeat;
NotifyDependentsIntervalChanged(interval_); NotifyDependentsIntervalChanged(interval_);
ScheduleRepeatEvents(); ScheduleRepeatEvents();
} }
last_percent_ = percent; last_percent_ = CalculateAnimationPercent(elapsed);
} }
if ((old_active_state == kActive && GetActiveState() != kActive) || if ((old_active_state == kActive && GetActiveState() != kActive) ||
......
...@@ -81,7 +81,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests { ...@@ -81,7 +81,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
SMILTime Elapsed() const; SMILTime Elapsed() const;
SMILTime IntervalBegin() const { return interval_.begin; } SMILTime IntervalBegin() const { return interval_.begin; }
SMILTime PreviousIntervalBegin() const { return previous_interval_begin_; } SMILTime PreviousIntervalBegin() const { return previous_interval_.begin; }
SMILTime SimpleDuration() const; SMILTime SimpleDuration() const;
bool NeedsToProgress(double elapsed); bool NeedsToProgress(double elapsed);
...@@ -189,6 +189,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests { ...@@ -189,6 +189,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
SMILTime ResolveActiveEnd(SMILTime resolved_begin, SMILTime ResolveActiveEnd(SMILTime resolved_begin,
SMILTime resolved_end) const; SMILTime resolved_end) const;
SMILTime RepeatingDuration() const; SMILTime RepeatingDuration() const;
const SMILInterval& GetActiveInterval(double elapsed) const;
base::Optional<SMILInterval> CheckForNewRestartInterval(double elapsed); base::Optional<SMILInterval> CheckForNewRestartInterval(double elapsed);
void BeginListChanged(SMILTime event_time); void BeginListChanged(SMILTime event_time);
...@@ -278,8 +279,9 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests { ...@@ -278,8 +279,9 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
// This is the upcoming or current interval // This is the upcoming or current interval
SMILInterval interval_; SMILInterval interval_;
// This is the previous interval. It should always be non-overlapping and
SMILTime previous_interval_begin_; // "before" |interval_|.
SMILInterval previous_interval_;
unsigned active_state_ : 2; unsigned active_state_ : 2;
unsigned restart_ : 2; unsigned restart_ : 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment