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

Rework 'active' handling in SMILAnimationSandwich

This eliminates the handling/manipulation of the 'active_' vector in
SMILAnimationSandwich. This vector contains the currently active
animations, and needn't be updated at the same time as timing, so move
the updating of it to a new method UpdateActiveAnimationStack().

All the clearing of the "result element" is moved to the sandwich.

Bug: 998526
Change-Id: Ic44d9265db93ea2de69b446856778f53feb6e92d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1796322
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695689}
parent 0b8abe70
......@@ -31,7 +31,7 @@
namespace blink {
SMILAnimationSandwich::SMILAnimationSandwich() {}
SMILAnimationSandwich::SMILAnimationSandwich() = default;
void SMILAnimationSandwich::Schedule(SVGSMILElement* animation) {
DCHECK(!sandwich_.Contains(animation));
......@@ -42,12 +42,15 @@ void SMILAnimationSandwich::Unschedule(SVGSMILElement* animation) {
auto* position = std::find(sandwich_.begin(), sandwich_.end(), animation);
DCHECK(sandwich_.end() != position);
sandwich_.erase(position);
if (animation == ResultElement())
animation->ClearAnimatedType();
}
void SMILAnimationSandwich::Reset() {
for (SVGSMILElement* animation : sandwich_) {
if (SVGSMILElement* result_element = ResultElement())
result_element->ClearAnimatedType();
for (SVGSMILElement* animation : sandwich_)
animation->Reset();
}
}
void SMILAnimationSandwich::UpdateTiming(double elapsed) {
......@@ -56,21 +59,13 @@ void SMILAnimationSandwich::UpdateTiming(double elapsed) {
std::sort(sandwich_.begin(), sandwich_.end(), PriorityCompare(elapsed));
}
active_.Shrink(0);
active_.ReserveCapacity(sandwich_.size());
for (const auto& it_animation : sandwich_) {
SVGSMILElement* animation = it_animation.Get();
for (const auto& animation : sandwich_) {
DCHECK(animation->HasValidTarget());
if (animation->NeedsToProgress(elapsed)) {
bool interval_restart = animation->CheckAndUpdateInterval(elapsed);
animation->UpdateActiveState(elapsed, interval_restart);
active_.push_back(animation);
} else if (animation->IsContributing(elapsed)) {
active_.push_back(animation);
} else {
animation->ClearAnimatedType();
}
if (!animation->NeedsToProgress(elapsed))
continue;
bool interval_restart = animation->CheckAndUpdateInterval(elapsed);
animation->UpdateActiveState(elapsed, interval_restart);
}
}
......@@ -95,30 +90,38 @@ SMILTime SMILAnimationSandwich::NextProgressTime(
}
void SMILAnimationSandwich::UpdateSyncBases(double elapsed) {
for (auto& animation : active_)
for (auto& animation : sandwich_)
animation->UpdateSyncBases();
}
SVGSMILElement* SMILAnimationSandwich::ResultElement() const {
return !active_.IsEmpty() ? active_.front() : nullptr;
}
auto* it = active_.begin();
while (it != active_.end()) {
auto* scheduled = it->Get();
if (scheduled->IsContributing(elapsed)) {
it++;
void SMILAnimationSandwich::UpdateActiveAnimationStack(
double presentation_time) {
SVGSMILElement* old_result_element = ResultElement();
active_.Shrink(0);
active_.ReserveCapacity(sandwich_.size());
// Build the contributing/active sandwich.
for (auto& animation : sandwich_) {
if (!animation->IsContributing(presentation_time))
continue;
}
scheduled->ClearAnimatedType();
it = active_.erase(it);
active_.push_back(animation);
}
// If we switched result element, clear the old one.
if (old_result_element && old_result_element != ResultElement())
old_result_element->ClearAnimatedType();
}
SVGSMILElement* SMILAnimationSandwich::ApplyAnimationValues() {
if (active_.IsEmpty())
SVGSMILElement* result_element = ResultElement();
if (!result_element)
return nullptr;
// Results are accumulated to the first animation that animates and
// contributes to a particular element/attribute pair.
// Only reset the animated type to the base value once for
// the lowest priority animation that animates and
// contributes to a particular element/attribute pair.
SVGSMILElement* result_element = active_.front();
result_element->ResetAnimatedType();
// Animations have to be applied lowest to highest prio.
......@@ -137,10 +140,8 @@ SVGSMILElement* SMILAnimationSandwich::ApplyAnimationValues() {
sandwich_it++) {
(*sandwich_it)->UpdateAnimatedValue(result_element);
}
active_.Shrink(0);
result_element->ApplyResultsToTarget();
return result_element;
}
......
......@@ -48,10 +48,12 @@ struct PriorityCompare {
double elapsed_;
};
// This class implements/helps with implementing the "sandwich model" from SMIL.
// https://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-AnimationSandwichModel
class SMILAnimationSandwich : public GarbageCollected<SMILAnimationSandwich> {
public:
using ScheduledVector = HeapVector<Member<SVGSMILElement>>;
explicit SMILAnimationSandwich();
SMILAnimationSandwich();
void Schedule(SVGSMILElement* animation);
void Unschedule(SVGSMILElement* animation);
......@@ -59,6 +61,7 @@ class SMILAnimationSandwich : public GarbageCollected<SMILAnimationSandwich> {
void UpdateTiming(double elapsed);
void UpdateSyncBases(double elapsed);
void UpdateActiveAnimationStack(double elapsed);
SVGSMILElement* ApplyAnimationValues();
SMILTime NextInterestingTime(double presentation_time) const;
......@@ -69,8 +72,17 @@ class SMILAnimationSandwich : public GarbageCollected<SMILAnimationSandwich> {
void Trace(blink::Visitor*);
private:
// The list stored here is always sorted.
// Results are accumulated to the first animation element that animates and
// contributes to a particular element/attribute pair. We refer to this as
// the "result element".
SVGSMILElement* ResultElement() const;
// All the animation (really: timed) elements that make up the sandwich,
// sorted according to priority.
ScheduledVector sandwich_;
// The currently active animation elements in the sandwich. Retains the
// ordering of elements from |sandwich_| when created. This is the animation
// elements from which the animation value is computed.
ScheduledVector active_;
};
......
......@@ -518,6 +518,7 @@ void SMILTimeContainer::ApplyAnimationValues(double elapsed) {
#endif
HeapVector<Member<SVGSMILElement>> animations_to_apply;
for (auto& sandwich : active_sandwiches_) {
sandwich->UpdateActiveAnimationStack(elapsed);
if (SVGSMILElement* animation = sandwich->ApplyAnimationValues())
animations_to_apply.push_back(animation);
}
......
......@@ -270,8 +270,6 @@ static inline void ClearTimesWithDynamicOrigins(
}
void SVGSMILElement::Reset() {
ClearAnimatedType();
active_state_ = kInactive;
is_waiting_for_first_interval_ = true;
interval_ = {SMILTime::Unresolved(), SMILTime::Unresolved()};
......
......@@ -556,8 +556,8 @@ float SVGAnimateElement::CalculateDistance(const String& from_string,
void SVGAnimateElement::WillChangeAnimationTarget() {
SVGAnimationElement::WillChangeAnimationTarget();
if (targetElement())
ClearAnimatedType();
// Should be cleared by the above.
DCHECK(!animated_value_);
}
void SVGAnimateElement::DidChangeAnimationTarget() {
......
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