Commit 8b99655c authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Rework SMIL interval re-scheduling on target changes

This reworks the way the interval is updated when the animation target
changes. The code to handle "connect" and "disconnect" from the time
container is moved into new methods AddedTo/RemovedFromTimeContainer(),
which does tasks that was previously sprinkled about in
SetTargetElement() and InsertedInto() and SMILTimeContainer::Schedule().
The call to ResetCachedAnimationState() in SVGAnimateElement is moved to
the "removal" side since we now revalidate the animation state via
SVGSMILElement::DidChangeAnimationTarget().

Bug: 998526
Change-Id: Ib6e847330cebc503cbca4a7cbd308b7a7ccc733a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1837832Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#702513}
parent 854ff8ea
......@@ -106,13 +106,6 @@ void SMILTimeContainer::Schedule(SVGSMILElement* animation,
sandwich = MakeGarbageCollected<SMILAnimationSandwich>();
sandwich->Schedule(animation);
SMILTime latest_update = CurrentDocumentTime();
if (animation->IntervalBegin() <= latest_update ||
animation->NextProgressTime(latest_update).IsFinite()) {
MarkIntervalsDirty();
ScheduleIntervalUpdate();
}
}
void SMILTimeContainer::Unschedule(SVGSMILElement* animation,
......
......@@ -290,16 +290,7 @@ Node::InsertionNotificationRequest SVGSMILElement::InsertedInto(
SMILTimeWithOrigin(SMILTime(), SMILTimeOrigin::kAttribute));
}
if (is_waiting_for_first_interval_)
ResolveFirstInterval();
if (time_container_) {
time_container_->MarkIntervalsDirty();
time_container_->ScheduleIntervalUpdate();
}
BuildPendingResource();
return kInsertionDone;
}
......@@ -597,19 +588,8 @@ void SVGSMILElement::SetTargetElement(SVGElement* target) {
if (target == target_element_)
return;
WillChangeAnimationTarget();
// If the animation state is not Inactive, always reset to a clear state
// before leaving the old target element.
if (GetActiveState() != kInactive)
EndedActiveInterval();
target_element_ = target;
DidChangeAnimationTarget();
// If the animation is scheduled and there's an active interval, then
// revalidate the animation value.
if (GetActiveState() != kInactive && is_scheduled_)
StartedActiveInterval();
}
SMILTime SVGSMILElement::Elapsed() const {
......@@ -941,6 +921,30 @@ void SVGSMILElement::UpdateInterval(SMILTime presentation_time) {
interval_has_changed_ = true;
}
void SVGSMILElement::AddedToTimeContainer() {
DCHECK(time_container_);
if (is_waiting_for_first_interval_)
ResolveFirstInterval();
SMILTime current_presentation_time = time_container_->CurrentDocumentTime();
if (IntervalBegin() <= current_presentation_time ||
NextProgressTime(current_presentation_time).IsFinite()) {
time_container_->MarkIntervalsDirty();
time_container_->ScheduleIntervalUpdate();
}
// If there's an active interval, then revalidate the animation value.
if (GetActiveState() != kInactive)
StartedActiveInterval();
}
void SVGSMILElement::RemovedFromTimeContainer() {
DCHECK(time_container_);
// If the element is active reset to a clear state.
if (GetActiveState() != kInactive)
EndedActiveInterval();
}
const SMILInterval& SVGSMILElement::GetActiveInterval(SMILTime elapsed) const {
// If there's no current interval, return the previous interval.
if (!interval_.IsResolved())
......@@ -1247,6 +1251,7 @@ void SVGSMILElement::WillChangeAnimationTarget() {
DCHECK(time_container_);
DCHECK(target_element_);
time_container_->Unschedule(this, target_element_, attribute_name_);
RemovedFromTimeContainer();
is_scheduled_ = false;
}
......@@ -1255,6 +1260,7 @@ void SVGSMILElement::DidChangeAnimationTarget() {
if (!time_container_ || !HasValidTarget())
return;
time_container_->Schedule(this, target_element_, attribute_name_);
AddedToTimeContainer();
is_scheduled_ = true;
}
......
......@@ -223,6 +223,9 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
void ConnectConditions();
void DisconnectConditions();
void AddedToTimeContainer();
void RemovedFromTimeContainer();
void NotifyDependentsOnNewInterval(const SMILInterval& interval);
void NotifyDependentsOnRepeat(unsigned repeat_nr, SMILTime repeat_time);
......
......@@ -550,6 +550,7 @@ void SVGAnimateElement::WillChangeAnimationTarget() {
SVGAnimationElement::WillChangeAnimationTarget();
// Should be cleared by the above.
DCHECK(!animated_value_);
ResetCachedAnimationState();
}
void SVGAnimateElement::DidChangeAnimationTarget() {
......@@ -557,7 +558,6 @@ void SVGAnimateElement::DidChangeAnimationTarget() {
// HasValidTarget() which depends on the animation type being resolved.
UpdateTargetProperty();
SVGAnimationElement::DidChangeAnimationTarget();
ResetCachedAnimationState();
}
void SVGAnimateElement::SetAttributeName(const QualifiedName& attribute_name) {
......
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